4

更改页面时取消挂起的 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来防止两个消费者发出相同的请求;但由于这种可观察到的模式是半热的,我不确定正确的做法是什么。更不用说取消它了。

任何和所有的帮助将不胜感激。

4

2 回答 2

6

取消 http 调用的最简单方法是取消订阅。

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

您的teardown方法很有用,通常用作垃圾收集并取消任何待处理的 rxjs 可观察对象。您可以在服务/组件/指令 ngOnDestroy 挂钩中调用它,以确保没有可观察的数据保留在内存中。

但如果我没记错的话,角度处理 http observables,所以你不需要处理它们。一般来说,你只需要处理你自己生成的 observables,比如你的BehaviorSubject.

于 2019-02-08T18:05:25.690 回答
1

我解决了将 Promises(异步函数)与 AbortSignal / AbortController 一起使用的问题,因为在我的情况下,尽管主题已取消,但 http 请求并未取消。也许我犯了一个错误,或者它现在可以工作了。但是,带有 AbortController 的 Promises 也可以完成这项工作。

请参阅此处如何使用 AbortController。但是,使用 AbortController 时可能存在浏览器兼容性问题。

您还可以使用 .toPromise() 将 observables 转换为 Promise,因此这应该不是问题。

于 2019-02-08T17:04:13.767 回答