带超时和检查RxJs可观察值轮询的递归函数

带超时和检查RxJs可观察值轮询的递归函数,rxjs,observable,settimeout,Rxjs,Observable,Settimeout,我有一个递归函数:repeatAlert,如果data.answered===null,就会再次调用该函数: 。。。。 编辑 this.repeatAlert(id).subscribe( val => console.log(val)); console.log('1stCall Alert: ', new Date().getMinutes()); find(id:number):可观察{ 返回this.http.get(`${this.resourceUr

我有一个递归函数:
repeatAlert
,如果
data.answered===null
,就会再次调用该函数:

。。。。 编辑

      this.repeatAlert(id).subscribe( val => console.log(val));
      console.log('1stCall Alert: ', new Date().getMinutes());

find(id:number):可观察{
返回this.http.get(`${this.resourceUrl}ByAlertId/${id}`
}
repeatAlert(id:编号){
this.find(id).subscribe((数据:AlertInt)=>{
if(data.answered==null){
这个.sendNotification('Alert',data.text);
log('Call Alert:',new Date().getMinutes(),data.id);
设置超时(()=>{
if(data.answered==null){
此.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)
    ),
  );
}
find(id:number):可观察{
返回this.http.get(`${this.resourceUrl}ByAlertId/${id}`;
}
repeatAlert(id:编号){
//从端点请求数据并执行必要的代码
const data$=this.find(id).pipe(
点击(数据=>{
if(data.answered==null){
这个.sendNotification('Alert',data.text);
}
})
);
//如果第一次尝试时没有数据,将开始轮询。已回答
const startPolling=(持续时间:number)=>计时器(持续时间,持续时间).pipe(
//假设(10),//我们想在10次尝试后停止
concatMap(()=>data$),
takeWhile(data=>data.answered==null),//何时停止轮询
);
//如果data.answered在第一次尝试时为null,则切换到轮询结束
返回数据$.pipe(
switchMap(数据=>data.Answeed===null?
开始滚动(data.repeating*1000*60):
(数据)
),
);
}
还请注意,我更改了您的
repeatAlert
,最好从方法中返回Observable并自行订阅,以避免内存泄漏。您应该自行订阅和取消订阅。此外,我建议您使用
take(10)
作为示例,这样轮询就不会无限期地继续,这取决于您


计时器(dueTime,period)
的工作原理如下:
它将在
dueTime
之后发出第一个事件,并在每个
时段之后继续发出事件


Edittakewhilecondition为true而not condition为false

我发现这段代码也在工作

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

我忘了在后端发送
数据。已回答
字段…所以总是空的

很棒的Anwser!@Goga。你有什么建议我可以在哪里学好RxJS:-)?我编辑了这个问题,这样你就可以看到结果了!哈哈,很高兴它有帮助。很多真实世界的使用经验,阅读官方api文档和关于RxJS的文章。我为朋友创建了一个关于RxJS的好资源小列表,请看一下:
  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);
      }
    });
  }