I have the recursive function: repeatAlert
that is called again if data.answered === null
:
.... Edit
this.repeatAlert(id).subscribe( val => console.log(val));
console.log('1stCall Alert: ', new Date().getMinutes());
....
find(id: number): Observable<any> {
return this.http.get(`${this.resourceUrl}ByAlertId/${id}`
}
repeatAlert(id: number) {
this.find(id).subscribe((data: AlertInt) => {
if (data.answered === null ) {
this.sendNotification('Alert ', data.text);
console.log('Call Alert: ', new Date().getMinutes(), data.id);
setTimeout(() => {
if (data.answered === null) {
this.repeatAlert(id);
}
}, data.repeating * 1000 * 60);
}
});
}
When I change the value of data.answered
in the database, I can't read with this observable find(id)
the change of data.answered
. So it keeps calling repeatAlert
forever ...
What am I doing wrong?
Extra question: Is it better a loop or recursive function ?
You are doing polling. I suggest something like following:
find(id: number): Observable<any> {
return this.http.get(`${this.resourceUrl}ByAlertId/${id}`;
}
repeatAlert(id: number) {
// request data from the endpoint and execute necessary code
const data$ = this.find(id).pipe(
tap(data => {
if (data.answered === null) {
this.sendNotification('Alert ', data.text);
}
})
);
// polling will start if on the first try we don't have data.answered
const startPolling = (duration: number) => timer(duration, duration).pipe(
//take(10), // let's say we want to stop after 10 tries
concatMap(() => data$),
takeWhile(data => data.answered === null), // when to stop polling
);
// if data.answered is null on the first try switch to polling otherwise end
return data$.pipe(
switchMap(data => data.answered === null ?
startPolling(data.repeating * 1000 * 60) :
of(data)
),
);
}
Also note that I changed your repeatAlert
, it's better to return Observable from the method and subscribe yourself to avoid memory leaks. You should subscribe and unsubscribe yourself. Also, I suggest you to use take(10)
for example so that polling doesn't continue indefinitely, it's up to you.
timer(dueTime, period)
works like this: It will emit first event after dueTime
and continue emitting events after every period
.
Edit takeWhile condition is true and not condition is false