Как отменить ожидающий запрос во внутреннем HTTP, наблюдаемом с RXJS?

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

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

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

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

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

Нет Буэно.

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

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 ответа

Решение

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

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

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

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

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

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

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

Другие вопросы по тегам