带超时的递归函数和检查 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