У меня есть служба, которая должна возвращать дату каждую секунду:
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, и документы не помогают.
вы должны return
setInterval
Сначала вы должны вернуть 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());
}
}
Observable.interval()
выдаст серию целых чисел 1, 2, 3, ...
, значение которой вы просто отбрасываете (() =>
) и заменяете на Date
, используя .map()
.
Вы можете оставить HeaderComponent
без изменений.
Примечание: я удалил назначение this.mydate
, потому что он не нужен казаться. Я заметил, что многие люди, переходящие на angular, создают ненужные промежуточные переменные-члены из рефлекса, когда достаточно чисто функционального решения. Если я был излишне самонадеян и вам это нужно, вы всегда можете вернуть его.
Вам также не нужен пустой constructor
в Angular, поэтому я удалил и его.
Однако вам делать нужны два дополнительных import
.
Вы зарегистрировали эту услугу в качестве провайдера в
app.module
?