Подписка на сервис из компонента в Angular 2+

У меня есть служба, которая должна возвращать дату каждую секунду:

import { Injectable } from '@angular/core';

import {Observable} from 'rxjs/Observable';

@Injectable()
export class ClockService {

    mydate: Date;

  constructor() {
  }

  getClock(): Observable<any> {
      setInterval(()=>{
          this.mydate = new Date();
          return this.mydate;
      }, 1000);
  }

}

Я пытаюсь подписаться на функцию getClock(), чтобы обновить mydate в моем компоненте:

import { Component, OnInit } from '@angular/core';
import {ClockService} from './clock.service';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.scss']
})
export class HeaderComponent implements OnInit {



  constructor(private clockService: ClockService) { }

  ngOnInit() {
      console.info(this.clockService.getClock().subscribe(res => this.mydate = res));
  }

}

Я получаю сообщение об ошибке: ERROR TypeError: Cannot read property 'subscribe' of undefined

Я новичок в Angular 2, и документы не помогают.

Вы зарегистрировали эту услугу в качестве провайдера в app.module?

Sravan 02.05.2018 15:43

вы должны returnsetInterval

Sravan 02.05.2018 15:45
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
1
2
323
3

Ответы 3

Сначала вы должны вернуть Observable в сервисную службу.

getClock(): Observable<any> {
  return new Observable(observer => {
    setInterval(()=>{
      this.mydate = new Date();
      observer.next(this.mydate);
    }, 1000);
  });
}

Фактически вы возвращаете не наблюдаемое, а вместо этого void в getClock().

См. https://angular.io/guide/observables

Вместо этого сделайте что-нибудь вроде этого:

import { Injectable } from '@angular/core';

import {Observable} from 'rxjs/Observable';

@Injectable()
export class ClockService {

  private $timer = new Observable(obs => {
      setInterval(() => {
          obs.next(new Date());
      }, 1000);
  });

  constructor() {
  }

  getClock(): Observable<Date> {
      return this.$timer;
  }

}

Нет необходимости реализовывать setInterval с Rx.

Вот еще один вариант с Observable.interval, который создает Observable, который испускает новое значение с заданным интервалом, что именно то, что вы хотите сделать:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/interval';
import 'rxjs/add/operator/map';

@Injectable()
export class ClockService {    
  getClock(): Observable<Date> {
      return Observable.interval(1000).map(() => new Date());
  }
}

Посмотреть в StackBlitz

Observable.interval() выдаст серию целых чисел 1, 2, 3, ..., значение которой вы просто отбрасываете (() =>) и заменяете на Date, используя .map().

Вы можете оставить HeaderComponent без изменений.

Примечание: я удалил назначение this.mydate, потому что он не нужен казаться. Я заметил, что многие люди, переходящие на angular, создают ненужные промежуточные переменные-члены из рефлекса, когда достаточно чисто функционального решения. Если я был излишне самонадеян и вам это нужно, вы всегда можете вернуть его.

Вам также не нужен пустой constructor в Angular, поэтому я удалил и его.

Однако вам делать нужны два дополнительных import.

Другие вопросы по теме