在您的代码中按顺序链接Observables
关于您的代码示例,如果您想链接Observables(在前一个发出后触发另一个),请使用flatMap
(或switchMap
)来实现此目的:
this.serviceA.get()
.flatMap((res1: any) => this.serviceB.get())
.flatMap((res2: any) => this.serviceC.get())
.subscribe( (res3: any) => {
....
});
与嵌套相比,这种做法更好,因为它会使问题更加清晰,并帮助您避免回调地狱,这也是 Observable 和 Promises 一开始就应该帮助防止的。
此外,请考虑使用 switchMap
而不是 flatMap
,基本上它将允许在第一个请求发出新值时“取消”其他请求。例如,如果第一个触发其余请求的 Observable 是某个按钮的点击事件,则可以使用此选项。
如果您不需要各种请求依次等待彼此,可以使用 forkJoin
或 zip
同时启动它们,有关详细信息和其他见解,请参见 @Dan Macak answer's。
Angular 'async' 管道和 Observables 很好地协同工作
关于 Observables 和 Angular,您可以完全在 Angular 模板中使用 | async
管道,而不是在组件代码中订阅 Observable,以获取由此 Observable 发出的值。
ES6 async / await 和 Promise 而不是 Observables?
如果你不想直接使用 Observable,你可以简单地在你的 Observable 上使用 .toPromise()
,然后一些 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 将等待 10 秒钟才解析“hi”。如果 Observable 永远不完成,则 Promise 永远不会解析。
注意:除非处理期望 Promise 的 API(例如 async-await)的情况,否则使用 toPromise()是一种反模式。
(强调是我自己加的)
您请求的示例
顺便说一句,如果有人能给我一个用 async/await 来解决这个问题的示例代码,那就太好了:D
如果你真的想这样做,那么以下是一个示例代码(可能会有些错误,无法检查,请随意更正)
async myFunction() {
const res1 = await this.serviceA.get().toPromise();
const res2 = await this.serviceB.get().toPromise();
const res3 = await this.serviceC.get().toPromise();
}
在您可以同时启动所有请求的情况下,
await Promise.all()
应该更有效,因为这些调用之间互不依赖。(就像Observables会使用
forkJoin
一样)
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]);
}
this.serviceA.get().flatMap((res1: any) => this.serviceB.get()).flatMap((res2: any) => this.serviceC.get()).subscribe( (res3: any) => { .... });
- Pac0