Reputation: 11187
I have a service that needs to return the date every second:
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);
}
}
I'm trying to subscribe to the getClock()
function to update mydate
in my component:
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.log(this.clockService.getClock().subscribe(res => this.mydate = res));
}
}
I'm getting an error of, ERROR TypeError: Cannot read property 'subscribe' of undefined
I'm new to Angular 2 and the docs aren't helping.
Upvotes: 1
Views: 364
Reputation: 12247
There's no need to implement setInterval
with Rx.
Here's another option with Observable.interval
which creates an Observable that emits a new value at the specified interval, which is exactly what you want to do:
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()
will emit a series of integers 1, 2, 3, ...
, whose value you simply discard (() =>
) and replace with a Date
, using .map()
.
You can keep your HeaderComponent
unchanged.
Note: I've removed the assignment to this.mydate
because it doesn't seem to be needed. I've noticed that many people moving to angular create unnecessary intermediary member variables out of reflex, when a purely functional solution suffices. If I've been overly presumptuous and you need it, you can always put it back.
You also don't need an empty constructor
in Angular, so I removed that too.
You do need the two additional import
s, though.
Upvotes: 2
Reputation: 13
You are not actually returning an observable but instead void
in getClock()
.
See https://angular.io/guide/observables
Instead do something like this:
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;
}
}
Upvotes: 1
Reputation: 38189
You should return an Observable
at your service function first.
getClock(): Observable<any> {
return new Observable(observer => {
setInterval(()=>{
this.mydate = new Date();
observer.next(this.mydate);
}, 1000);
});
}
Upvotes: 2