按顺序链接 Observables,就像你想在你的代码中做的那样
关于您的代码示例,如果您想链接 Observables(在前一个发出后触发另一个),请为此使用flatMap
(或switchMap
):
this.serviceA.get()
.flatMap((res1: any) => this.serviceB.get())
.flatMap((res2: any) => this.serviceC.get())
.subscribe( (res3: any) => {
....
});
与嵌套相比,这是更好的实践,因为这将使事情更清晰并帮助您避免回调地狱,而 Observable 和 Promise 应该首先帮助防止。
此外,考虑使用switchMap
而不是flatMap
,如果第一个请求发出新值,它基本上将允许“取消”其他请求。例如,如果触发其余部分的第一个 Observable 是按钮上的某个点击事件,则使用起来很好。
如果您不需要您的各种请求轮流等待彼此,您可以使用forkJoin
或zip
同时启动它们,有关详细信息和其他见解,请参阅@Dan Macak 的回答。
Angular 'async' 管道和 Observables 可以很好地协同工作
关于 Observables 和 Angular,你可以完美地| async
在 Angular 模板中使用管道,而不是在你的组件代码中订阅 Observable,来获取这个 Observable 发出的值
ES6 async / await 和 Promises 而不是 Observables ?
如果你不觉得直接使用 Observable,你可以简单地.toPromise()
在你的 Observable 上使用,然后是一些 async/await 指令。
如果您的 Observable 应该只返回一个结果(就像基本 API 调用的情况一样),则 Observable 可以被视为与 Promise 相当。
但是,考虑到 Observable 已经提供的所有内容,我不确定是否需要这样做(对读者来说:欢迎提供启发性的反例!)。我更倾向于尽可能使用 Observables 作为训练练习。
一些有趣的博客文章(还有很多其他的):
https://medium.com/@benlesh/rxjs-observable-interop-with-promises-and-async-await-bebb05306875
toPromise 函数实际上有点棘手,因为它并不是真正的“运算符”,而是一种 RxJS 特定的订阅 Observable 并将其包装在Promise中的方法。一旦 Observable 完成,promise 将解析为 Observable 最后发出的值。这意味着如果 Observable 发出值“hi”然后在它完成之前等待 10 秒,返回的 Promise 将在解析“hi”之前等待 10 秒。如果 Observable 永远不会完成,那么 Promise 永远不会解决。
注意:使用 toPromise() 是一种反模式,除非您正在处理需要 Promise 的 API,例如 async-await
(强调我的)
你要求的例子
顺便说一句,如果有人能给我一个示例代码来用 async/await 解决这个问题,那就太好了:D
例子如果你真的想做(可能有一些错误,现在无法检查,请随时纠正)
// Warning, probable anti-pattern below
async myFunction() {
const res1 = await this.serviceA.get().toPromise();
const res2 = await this.serviceB.get().toPromise();
const res3 = await this.serviceC.get().toPromise();
// other stuff with results
}
在这种情况下,您可以同时启动所有请求,await Promise.all()
这应该会更有效率,因为没有一个调用依赖于彼此的结果。(就像forkJoin
Observable 一样)
async myFunction() {
const promise1 = this.serviceA.get().toPromise();
const promise2 = this.serviceB.get().toPromise();
const promise3 = this.serviceC.get().toPromise();
let res = await Promise.all([promise1, promise2, promise3]);
// here you can retrieve promises results,
// in res[0], res[1], res[2] respectively.
}