RxJS: Как определить (максимальную) продолжительность для (необязательного) запроса? - PullRequest
2 голосов
/ 13 мая 2019

У меня есть такая логика:

  public setXXXInLocalStorage(): Observable<boolean> {

    return this.appConfig.getEndpoint('xxx')
      .pipe(
        switchMap((endpoint: Endpoint) => this.http.get(endpoint.toUrl(), {headers})),
        map((body: any) => { localStorage.setItem('myItem', body.item); }),
        timeout(5000),
        map(() => true),
        catchError(() => of(true))
      );
  }

Чего я хотел добиться, так это того, что я хочу ждать макс. 5 секунд для моего запроса на получение.

  • switchmap: вызывает мою конечную точку
  • карта: разбирается с ответом
  • Тайм-аут: я пытался определить макс. 5 сек для этого звонка
  • карта: в случае успеха мы ничего не должны делать, а просто возвращаем true
  • catchError: если в запросе возникает какая-либо ошибка или происходит тайм-аут, мы также можем просто игнорировать ошибку и просто возвращать true

То, что сейчас происходит: время ожидания всегда составляет 5 секунд, даже если мой запрос на получение возвращает успех через 1 секунду.

Заранее спасибо ..

Ответы [ 2 ]

0 голосов
/ 14 мая 2019

я думаю, что это решило мою проблему: как отменить подписку RXJS через некоторое время

От @Kroltan:

Очевидно, клиент rxjs поддерживает наблюдаемую работупосле получения значения (предположительно, так вы получите уведомление о дальнейших обновлениях).А так как Observable никогда не завершается, Timeout будет действовать через 30 (или что бы вы ни проходили как длительность) секунд после получения данных, вызывая сбой потока.Наблюдаемое событие, используйте оператор Take до истечения времени ожидания:

Так что мне просто нужно было добавить дубль (1) до истечения времени ожидания.

public setXXXInLocalStorage(): Observable<boolean> {

    return this.appConfig.getEndpoint('xxx')
      .pipe(
        switchMap((endpoint: Endpoint) => this.http.get(endpoint.toUrl(), {headers})),
        tap((body: any) => { localStorage.setItem('myItem', body.item); }),
        take(1),
        timeout(5000),
        map(() => true),
        catchError(() => of(true))
      );
  }
0 голосов
/ 13 мая 2019

Когда оператор timeout следует за оператором map, значение, возвращаемое из обратного вызова оператору map, важно, поскольку оно определяет, какое значение передается логике timeout.Поскольку в вашей операции map нет возвращаемого значения, то оператору timeout передается undefined, когда он оценивает наблюдаемое излучение из источника (HTTP get).

Поскольку наблюдаемоеundefined никогда не завершается, тогда оператор timeout всегда выдаст ошибку (по истечении указанного времени).

Вместо использования map для побочного эффекта установки значения в локальном хранилище,используйте tap, который просто переправит наблюдаемый источник на следующий оператор в трубе.

const endpoint = rxjs.of('blah');

function getRequest(httpObservable, name) {
  return endpoint.pipe(
    rxjs.operators.switchMap(() => httpObservable),
    rxjs.operators.tap((val) => { // Call `tap` instead of `map`
      console.log(`${name}: ${val}`);
    }),
    rxjs.operators.timeout(2000),
    rxjs.operators.map(() => true),
  ).subscribe(
    null,
    () => console.log(`${name} Errored!`),
    () => console.log(`${name} Complete!`)
  );
}

const http = rxjs.timer(500);
const slowHttp = rxjs.timer(4000);

getRequest(http, 'Quick HTTP');
getRequest(slowHttp, 'Slow HTTP');
<script src="https://unpkg.com/@reactivex/rxjs@6.5.2/dist/global/rxjs.umd.js"></script>
...