如何使用 RXJS 取消可观察到的内部 HTTP 中的待处理请求?
How to cancel a pending request in an inner HTTP observable with 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() 期间调用的服务中创建一个拆卸方法,但除非我完成流,否则它不起作用。但那时,当用户 returns 到页面时,我无法再次重新启动流。
tearDown(): void {
this.unsubscribe$.next();
this.unsubscribe$.complete();
// this.dataSubject.next(null);
// this.dataSubject.complete(); -- breaks
}
我绝不是 RXJS 专家,如果我的整体设计有误,请随时指出。我一直怀疑我应该使用 switchMap() 或 share 来防止两个消费者发出相同的请求;但是因为这种可观察到的模式是半热的,所以我不确定正确的做法是什么。更不用说取消了。
任何帮助都将不胜感激。
我解决了将 Promises(异步函数)与 AbortSignal / AbortController 结合使用的问题,因为在我的情况下,尽管主题已取消,但 http 请求并未取消。也许我犯了一个错误,或者它现在可以工作了。但是,带有 AbortController 的 Promises 也可以完成这项工作。
参见 here 如何使用 AbortController。但是,使用AbortController时可能存在浏览器兼容性问题。
您还可以使用 .toPromise() 将 observables 转换为 promise,这样这应该不是问题。
取消 http 调用的最简单方法是取消订阅。
const subscription: Subscription = this.http.post(...).subscribe(...);
subscription.unsubscribe();
您的 teardown
方法很有用,通常用作垃圾收集和取消任何挂起的 rxjs observables。您可以在 service/component/directive ngOnDestroy 挂钩中调用它,以确保没有可观察对象保留在内存中。
但如果我没记错的话,angular 处理 http observables,所以你不需要处理它们。一般来说,您只需要处理自己生成的可观察对象,例如您的 BehaviorSubject
.
更改页面时取消挂起的 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() 期间调用的服务中创建一个拆卸方法,但除非我完成流,否则它不起作用。但那时,当用户 returns 到页面时,我无法再次重新启动流。
tearDown(): void {
this.unsubscribe$.next();
this.unsubscribe$.complete();
// this.dataSubject.next(null);
// this.dataSubject.complete(); -- breaks
}
我绝不是 RXJS 专家,如果我的整体设计有误,请随时指出。我一直怀疑我应该使用 switchMap() 或 share 来防止两个消费者发出相同的请求;但是因为这种可观察到的模式是半热的,所以我不确定正确的做法是什么。更不用说取消了。
任何帮助都将不胜感激。
我解决了将 Promises(异步函数)与 AbortSignal / AbortController 结合使用的问题,因为在我的情况下,尽管主题已取消,但 http 请求并未取消。也许我犯了一个错误,或者它现在可以工作了。但是,带有 AbortController 的 Promises 也可以完成这项工作。
参见 here 如何使用 AbortController。但是,使用AbortController时可能存在浏览器兼容性问题。
您还可以使用 .toPromise() 将 observables 转换为 promise,这样这应该不是问题。
取消 http 调用的最简单方法是取消订阅。
const subscription: Subscription = this.http.post(...).subscribe(...);
subscription.unsubscribe();
您的 teardown
方法很有用,通常用作垃圾收集和取消任何挂起的 rxjs observables。您可以在 service/component/directive ngOnDestroy 挂钩中调用它,以确保没有可观察对象保留在内存中。
但如果我没记错的话,angular 处理 http observables,所以你不需要处理它们。一般来说,您只需要处理自己生成的可观察对象,例如您的 BehaviorSubject
.