具有超时和检查 RxJs 可观察值轮询的递归函数 [英] Recursive function with timeout and check RxJs Observable value polling

查看:61
本文介绍了具有超时和检查 RxJs 可观察值轮询的递归函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有递归函数:repeatAlert,如果data.answered === null:

I have the recursive function: repeatAlert that is called again if 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的变化.回答.所以它一直在调用 repeatAlert 永远......

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 ...

我做错了什么?

额外问题:循环还是递归函数更好?

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

另请注意,我更改了您的repeatAlert,最好从方法返回 Observable 并自己订阅以避免内存泄漏.您应该自己订阅和取消订阅.另外,我建议您使用 take(10) 为例,以便轮询不会无限期地继续,这取决于您.

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) 的工作原理如下: 它会在 dueTime 之后发出第一个事件,并在每个 之后继续发出事件期间.

timer(dueTime, period) works like this: It will emit first event after dueTime and continue emitting events after every period.

编辑 takeWhile 条件为真而非条件为假

Edit takeWhile condition is true and not condition is false

这篇关于具有超时和检查 RxJs 可观察值轮询的递归函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆