Note: I know there is a timer observable from rxjs, I am using this as a proof of concept to learn how observables work.
I have created a timer in angular that has a button to start, a text with the number of seconds ellapsed and a text with the state (stopped/executing/finished).
When I click the button, the current example starts running and the state changes to "executing" and the number of second changes. But when it gets to 5, it stops (the "finishing" log is shown and the number of seconds no longer changes) but the state does not change to "finished" (and neither the "finished" console log appears). And the error method is not executed, either.
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
@Component({
selector: 'app-reloj',
templateUrl: './reloj.component.html',
styleUrls: ['./reloj.component.css']
})
export class RelojComponent implements OnInit {
public time: number = 0;
public state: string = "Stopped";
private crono = new Observable<number>(
observer => {
let start: number = (new Date()).getTime();
let lastCount = 0;
(function repeat() {
let now: number = (new Date()).getTime();
let seconds = ((now - start) / 1000 | 0);
if (lastCount < seconds) {
observer.next(seconds);
if (seconds >= 5) {
console.log("Finishing");
return;
}
lastCount = seconds;
}
setTimeout(
repeat,
100);
})();
});
constructor() { }
ngOnInit(): void {
}
onStart(): void {
console.log("Starting");
let self = this;
this.state = "Executing";
this.crono.subscribe({
next(seconds: number) {
console.log(`At next ${seconds}`);
self.time = seconds;
},
error(err) {
console.log("Error");
},
complete() {
console.log("Finished");
self.state = "Finished";
}
})
}
}
and the html
<button (click)="onStart()">Start</button>
<div>{{time}}</div>
<div>{{state}}</div>
CodePudding user response:
You need to invoke observer.complete() to tell the subscriber that the operation completed.
if (seconds >= 5) {
console.log("Finishing");
observer.complete();
return;
}