Angular / RxJS Polling с тайм-аутом и интервалом, зависящим от времени отклика API - PullRequest
1 голос
/ 26 октября 2019

Я пытаюсь написать метод, который будет опрашивать состояние операции API, возвращая наблюдаемое, которое будет генерировать результат каждого вызова состояния (поскольку оно содержит информацию о ходе выполнения, которую я хотел бы отобразить), пока не получитстатус завершения, выдает этот статус, и затем это сделано.

То, что я имею до сих пор, таково:

pollStatus(identifier: string): Observable<OperationStatusResource> {
    const obs = interval(1000)
      .pipe(
        startWith(0),
        switchMap( () => this.apiService.operationStatus(identifier) ),
        takeWhile( (value, index) => { 
          return value.status != OPERATION_STATUS.COMPLETE;
        }, true)
      )

    return obs;
  }

, который работает, и я понимаю это, но я думаю, что могу добиться большего, и я изо всех сил пытаюсь понять, как. Это запрашивает новый статус каждую секунду и отменяет предыдущий, если он еще не завершен. Я действительно хочу отменить предыдущие запросы каждый раз, когда отправляю новый, чтобы гарантировать, что я никогда не выйду из строя из-за интернет-махинаций, но:

  • Я хотел бы применить задержку, начиная с моментаответ от последнего запроса. Так что, как и req-> resp-> 1000ms-> req и т. Д.
  • Я бы хотел установить тайм-аут для каждого запроса. Так, например, если запрос не вернул ответ через 5 секунд, я отменю его и попытаюсь снова

Я также был бы рад любому другому способу реализации той же самой идеи бытьпациент, если ответ занимает некоторое время, но не желает ждать вечно, и не запрашивает слишком быстро, если ответ возвращается быстро.

Бонусные баллы, если я могу добавить общее условие сбоя или тайм-аут, например, отказаться, если вы получаете 3 таймаута подряд или если все это занимает более 5 минут или если я получу 3 не 200 кода обратноряд.

1 Ответ

0 голосов
/ 28 октября 2019

После сна я думаю, что ЭТОТ ответ с добавленной повторной попыткой в ​​конце - это то, что я должен использовать.

pollStatus(identifier: string): Observable<OperationStatusResource> {
  const obs = defer(() => this.apiService.operationStatus(identifier))
    .pipe (
      timeout(10000),
      repeatWhen(notification => notification.pipe(delay(1000))),
      takeWhile( (value, index) => { 
        return value.status != OPERATION_STATUS.COMPLETE;
      }, true)
    ).pipe(retry(1))
  return obs;
}

Это сделает первоначальный запрос, затем подождитедля ответа в течение максимального количества мс (тайм-аут), и после получения ответа он будет ждать количество мс (задержка).

Повтор в конце это то, что мне нужно. Если истекло время ожидания, запрос будет отменен, и повторная попытка будет повторена (один раз, в этом примере)

...