javascript - 将 Observable 与 async/await 结合使用是一种好习惯吗?

标签 javascript angular typescript promise observable

我正在使用返回 Observable 的 angular 2 通用 http,但是当我使用嵌套的 Observable 调用时,我遇到了一个问题,即我的代码喜欢网格:

this.serviceA.get().subscribe((res1: any) => {
   this.serviceB.get(res1).subscribe((res2: any) => {
       this.serviceC.get(res2).subscribe((res3: any) => {

       })
   })
})

现在我想使用 async/await 来避免这种情况,但 async/await 只适用于 Promise。我知道 Observable 可以转换为 Promise 但据我所知,这不是一个好的做法。那么我应该在这里做什么?

顺便说一句,如果有人能给我一个用 async/await 解决这个问题的示例代码就太好了 :D

最佳答案

按顺序链接 Observable,就像你想在代码中做的那样

关于您的代码示例,如果您想链接 Observable(在前一个发出后触发另一个),请使用 flatMap(或 switchMap)用于此目的:

this.serviceA.get()
  .flatMap((res1: any) => this.serviceB.get())
  .flatMap((res2: any) => this.serviceC.get())
  .subscribe( (res3: any) => { 
    .... 
  });

与嵌套相比,这是更好的做法,因为这将使事情更清晰,并帮助您避免回调 hell ,Observable 和 Promises 本来应该有助于预防。

此外,考虑使用 switchMap 而不是 flatMap,基本上,如果第一个请求发出新值,它将允许“取消”其他请求。例如,如果触发其余部分的第一个 Observable 是按钮上的某个点击事件,则使用起来很不错。

如果你不需要你的各种请求依次等待,你可以使用forkJoin或者zip来一次启动它们,见@Dan Macak answer's详细信息和其他见解。


Angular 的“异步”管道和 Observables 可以很好地协同工作

关于Observables和Angular,可以完美使用| async 在 Angular 模板中使用管道而不是在组件代码中订阅 Observable,以获取此 Observable 发出的值


ES6 async/await 和 Promises 而不是 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

The toPromise function is actually a bit tricky, as it’s not really an “operator”, rather it’s an RxJS-specific means of subscribing to an Observable and wrap it in a promise. The promise will resolve to the last emitted value of the Observable once the Observable completes. That means that if the Observable emits the value “hi” then waits 10 seconds before it completes, the returned promise will wait 10 seconds before resolving “hi”. If the Observable never completes, then the Promise never resolves.

NOTE: using toPromise() is an antipattern except in cases where you’re dealing with an API that expects a Promise, such as async-await

(强调我的)


您请求的示例

BTW, it will be nice if anyone can give me an example code to solve this with 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.
}

关于javascript - 将 Observable 与 async/await 结合使用是一种好习惯吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49596641/

相关文章:

javascript - 如何在 angular2 或 typescript 中获取 ng-select 中的选项

javascript - 方法返回比属性更多的长度

angular - .NET Core 2.1 SignalR 使用 Angular 6 客户端进行长轮询的回退

javascript - 在 Chrome 扩展中插入图像?

angular - 你如何包含/扩展带有 rollup、typescript、angular 2 的 JS 库

json - 利用浏览器缓存 - Firebase/Angular 5

angular - 组件@Input继承

angular - 有没有办法防止 formControl 触发事件?

javascript - 如何循环遍历数组,并从数据库 Angular 5 获取一些数据

javascript - r.js 优化器 - 不要混淆函数名称