Recursive function with timeout and check RxJs Observable value polling

牧云@^-^@ 提交于 2020-06-16 17:57:51

问题


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 ?


回答1:


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




回答2:


I turns out that this code is also working

  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);
      }
    });
  }

I forget in the backend to send the data.answered field ... so was always null



来源:https://stackoverflow.com/questions/61231259/recursive-function-with-timeout-and-check-rxjs-observable-value-polling

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!