Рекурсивная функция с таймаутом и проверкой Rx Js Наблюдаемое значение опроса - PullRequest
1 голос
/ 15 апреля 2020

У меня есть рекурсивная функция: 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 навсегда ...

Что я делаю не так?

Дополнительный вопрос: лучше ли это oop или рекурсивная функция?

Редактировать


Результат с принятым ответом:

             Minute ID
1stCall Alert:  18
 Call Alert:  18 258136 
 Call Alert:  19 258136 
1stCall Alert:  20
 Call Alert:  20 258132 
1stCall Alert:  21
 Call Alert:  21 258140 
 Call Alert:  21 258132 
1stCall Alert:  21
 Call Alert:  21 258145 
1stCall Alert:  22
 Call Alert:  22 258136 
 Call Alert:  22 258140 
 Call Alert:  22 258145 
 Call Alert:  23 258136 
 cancelAlert: 258145
1stCall Alert:  24
 Call Alert:  24 258147 
1stCall Alert:  24
 Call Alert:  24 258140 
 Call Alert:  25 258147 
 Call Alert:  25 258140 
 cancelAlert: 258105
 cancelAlert: 258132
1stCall Alert:  27
Call Alert:  27 258147 
Call Alert:  28 258147 

1 Ответ

1 голос
/ 15 апреля 2020

Вы делаете опрос. Я предлагаю что-то вроде следующего:

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), например, чтобы опрос не продолжался бесконечно, вам решать.


timer(dueTime, period) работает так: Это будет генерировать первое событие после dueTime и продолжать генерировать события после каждого period.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...