【发布时间】:2020-02-23 10:59:13
【问题描述】:
我有一个包含 2 个步骤的 Angular 向导组件。在第一步中,向用户显示一个表单。在第二步中,另一个表单显示为长时间运行的 HTTP GET 的结果。目前这是可行的,当用户到达第二步时,会发出请求,最终用户会看到表单是长时间运行的调用的结果;但是,用户等待请求结束很烦人。
为了优化,我尝试在向导的第一步在后台触发长时间运行的请求,从而减少用户的等待时间。从技术上讲这是可能的,因为请求参数不依赖于步骤 1 中的用户操作。
然而,困难在于 Observables 什么都不做,除非你订阅它们。但是当我订阅 Observable 请求时,它将在向导步骤 1 中等待它完成(因此不会为用户带来性能提升)。
所以我需要以某种方式订阅可观察的请求,但在后台这样不会阻塞 begin 管道。
每个向导步骤都有一个onStepBegin 和onStepFinish。在第 1 步的onStepBegin 中,我想立即创建 observable 并执行请求。然后在第2步的onStepBegin中,应该等待请求的剩余时间。
从技术上讲,下面的代码可以工作,但请求不会早于步骤 2 被触发。我怎样才能让它在步骤 1 中立即触发请求?
我尝试了以下方法来修复它:
- 添加一个发布操作符使 observable 变热:没有帮助,因为它将在 订阅后变热
- 使用手动
subscribe()电话订阅;但是所谓的嵌套订阅似乎会造成内存泄漏
向导步骤 1:
public onStepBegin(begin: Observable<any>): Observable<MyContext> {
return begin.pipe(
tap(() => {
..
this.context.loadInitial = this.loadInitialConfigurations(this.selectedElementclass.id).pipe(
first(),
publish()
);
})
);
}
向导步骤 2:
public onStepBegin(begin: Observable<any>): Observable<MyContext> {
return begin.pipe(
switchMap(() => this.context.loadInitial),
tap((c) => {
this.context.configurations = c;
}),
);
【问题讨论】:
-
您是否尝试过将请求的生成与公开结果的 observable 分开?例如。在this blog post 中,我展示了如何拥有一个触发请求(
fetchRandomUser)的方法,该方法与结果的可观察(randomUser$)分开。在您的情况下,步骤 1 将立即调用触发方法,这会导致 service 订阅请求,步骤 2 将订阅结果。 -
感谢您的评论;我认为在这种情况下需要手动订阅,这并不是最好的解决方案,而且我害怕引入内存泄漏。如果我手动订阅,之后我将无法清理订阅。
-
清理什么?收到响应后,可观察到的请求完成,因此服务中的订阅不会永远挂起。
-
我认为你是对的,谢谢