Как отменить ожидающий запрос во внутреннем HTTP, наблюдаемом с RXJS? - PullRequest
0 голосов
/ 08 февраля 2019

Отмена ожидающего HTTP-запроса при изменении страницы

У нас есть служба Angular, которая имеет дорогой HTTP-запрос, доступ к которому могут получить 3 разных потребителя.Каждый потребитель может изменить этот запрос в любой момент, сделать новый запрос, и все другие потребители должны быть обновлены с новыми данными.

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

Проблема тогда, когда пользователь меняет страницуНельзя отменить текущий ожидающий ответ HTTP.

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

Нет bueno.

Сервисный вызов

private dataSubject = new BehaviorSubject<MyData>(...);
public data$ = this.dataSubject.asObservable();
...

getData(): Observable<MyData> {
  if (this.dataSubject)
    return this.data$;
  } else {
    const http$ = this.http.post(...))
      .pipe(map(response => response as MyData),
        takeUntil(this.unsubscribe$)); // see tearDown() below
    http$.subscribe(
      (availableDevices: MyData) => {
        this.dataSubject.next(availableDevices);
      }
    );
    return this.data$;
  }
}

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

tearDown(): void {
  this.unsubscribe$.next();
  this.unsubscribe$.complete();
  // this.dataSubject.next(null);
  // this.dataSubject.complete(); -- breaks
}

Я ни в коем случае не эксперт RXJS, поэтому не стесняйтесь указывать, если мойОбщий дизайн не так.У меня есть подозрение, что я должен использовать switchMap () или share , чтобы два потребителя не делали один и тот же запрос;но поскольку этот наблюдаемый паттерн полужесткий, я не уверен, каков правильный курс действий.Не говоря уже о том, чтобы отменить его.

Любая помощь будет принята с благодарностью.

Ответы [ 2 ]

0 голосов
/ 08 февраля 2019

Самый простой способ отменить вызов http - это отписаться от подписки.

const subscription: Subscription = this.http.post(...).subscribe(...);
subscription.unsubscribe();

Ваш teardown метод полезен и обычно используется как сборщик мусора и для отмены любых ожидающих наблюдений rxjs.Вы бы назвали это в ловушке service / component / directive ngOnDestroy, чтобы убедиться, что в памяти не осталось никаких наблюдаемых.

Но если я правильно помню, угловые обрабатывают наблюдаемые http, поэтому вам не нужно обрабатывать их,Вообще говоря, вам нужно только позаботиться о наблюдаемых вами факторах, таких как BehaviorSubject.

0 голосов
/ 08 февраля 2019

Я решил, что с помощью Promises (асинхронных функций) с AbortSignal / AbortController, потому что в моем случае запрос http не был отменен, хотя тема была отменена.Может быть, я ошибся или это сработало бы сейчас.Тем не менее, Promises с AbortController тоже справляются с этой задачей.

См. здесь , как использовать AbortController.Однако при использовании AbortController может возникнуть проблема с совместимостью браузера.

Вы также можете преобразовать наблюдаемые в обещания с помощью .toPromise (), чтобы это не вызывало проблем.

...