带超时的递归函数和检查 RxJs Observable 值轮询
Recursive function with timeout and check RxJs Observable value polling
我有递归函数:repeatAlert
如果 data.answered === null
:
再次调用
.....
编辑
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);
}
});
}
当我在数据库中更改 data.answered
的值时,我无法使用此可观察 find(id)
读取 data.answered
的更改。所以它一直在调用 repeatAlert
永远...
我做错了什么?
附加问题:循环函数好还是递归函数好?
您正在进行投票。我建议如下:
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)
),
);
}
另请注意,我更改了您的repeatAlert
,最好从方法中return Observable 并自行订阅以避免内存泄漏。您应该自己订阅和取消订阅。另外,我建议您使用 take(10)
作为示例,这样轮询就不会无限期地继续下去,这取决于您。
timer(dueTime, period)
的工作方式如下: 它会在 dueTime
之后发出第一个事件,并在每个 period
.[=16 之后继续发出事件=]
编辑 takeWhile 条件为真而不是条件为假
我发现这段代码也有效
repeatAlert(id: number) {
this.alertServ.find(id).subscribe((data: AlertInt) => {
if (data.answered === null) {
this.sendNotification( 'Alert ', data.text);
setTimeout(() => {
this.repeatAlert(id);
}, data.repeating * 1000 * 60);
}
});
}
我忘记在后端发送 data.answered
字段...因此始终为 null
我有递归函数:repeatAlert
如果 data.answered === null
:
..... 编辑
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);
}
});
}
当我在数据库中更改 data.answered
的值时,我无法使用此可观察 find(id)
读取 data.answered
的更改。所以它一直在调用 repeatAlert
永远...
我做错了什么?
附加问题:循环函数好还是递归函数好?
您正在进行投票。我建议如下:
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)
),
);
}
另请注意,我更改了您的repeatAlert
,最好从方法中return Observable 并自行订阅以避免内存泄漏。您应该自己订阅和取消订阅。另外,我建议您使用 take(10)
作为示例,这样轮询就不会无限期地继续下去,这取决于您。
timer(dueTime, period)
的工作方式如下: 它会在 dueTime
之后发出第一个事件,并在每个 period
.[=16 之后继续发出事件=]
编辑 takeWhile 条件为真而不是条件为假
我发现这段代码也有效
repeatAlert(id: number) {
this.alertServ.find(id).subscribe((data: AlertInt) => {
if (data.answered === null) {
this.sendNotification( 'Alert ', data.text);
setTimeout(() => {
this.repeatAlert(id);
}, data.repeating * 1000 * 60);
}
});
}
我忘记在后端发送 data.answered
字段...因此始终为 null