有大量关于使用“takeUntil”运算符取消订阅流的信息,如下所示:
...
export class CategoryOptionInputComponent
constructor(private svc: MyService, protected router: RouterService) {
...
this.router.routerUrl$.pipe(takeUntil(this.ngUnsubscribe)).subscribe(s => {
const param1 = s.state.featureId;
this.svc.InitFromApi(param1);
});
...
}
ngOnDestroy() {
this.ngUnsubscribe.next();//<-- This line is confusing
this.ngUnsubscribe.complete();
}
private readonly ngUnsubscribe = new Subject();
}
如上代码所示,我们需要在正在解析的路由器数据上从API加载数据,并在新的路由器数据到达时继续加载新数据,直到组件被销毁。
当用户导航到不同的路线时,预计组件将在未最后点击 API 的情况下被销毁。但是,它的行为并不像预期的那样。即使组件即将被销毁,也会调用 API。
我的问题是:
(1)如何防止组件在死前命中API?
(2) 为什么不只是 complete() 流,为什么在 complete() 之前调用 next() (见上面的代码)?
提前致谢。
最佳答案
1) 如果您希望 API 调用可取消,则它需要成为可观察链的一部分。当在 subscribe
中执行调用时,无法取消它,因此您必须为此使用运算符,例如 mergeMap
或 concatMap
.
this.router.routerUrl$.pipe(
takeUntil(this.ngUnsubscribe),
concatMap(s => {
const param1 = s.state.featureId;
return this.svc.InitFromApi(param1);
})
).subscribe();
但是,这需要 this.svc.InitFromApi()
返回 Observable 或 Promise。如果您在 InitFromApi()
内订阅或在 Promise 上使用 then()
,那么它会导致无法订阅。
2) takeUntil
就是这样设计的。它只对 next
通知使用react。如果您不想同时调用 next()
和 complete()
,您可以使用 defaultIfEmpty()
运算符:
this.router.routerUrl$.pipe(
takeUntil(this.ngUnsubscribe.pipe(
defaultIfEmpty(null),
))
).subscribe(...);
然后你可以调用 this.ngUnsubscribe.complete()
它也会触发 takeUntil
。
实际上,在您的示例中,如果您调用 next()
,您甚至不需要调用 complete()
,因为下一个通知将使链进行处理。
关于angular - 为什么在 Angular takeuntil ngUnsubscribe 的 'next' 之前有一个 'complete'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54174424/