将 Observable 与 async/await 一起使用是一个好习惯吗? [英] Is it a good practice using Observable with async/await?

查看:27
本文介绍了将 Observable 与 async/await 一起使用是一个好习惯吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using angular 2 common http that return an Observable, but I face with a problem that my code likes a mesh when I use nested Observable call:

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 但据我所知,这不是一个好习惯.那么我应该在这里做什么?

Now I wanna use async/await to avoid that but async/await only work with Promise. I know that Observable can be converted to Promise but as I know, it is not a good practice. So what should I do here ?

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

BTW, it will be nice if anyone can give me an example code to solve this with async/await :D

推荐答案

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

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

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

与嵌套相比,这是更好的实践,因为这将使事情更清晰并帮助您避免回调地狱,而 Observable 和 Promise 本来应该帮助防止的.

This one is better practice compared to nesting, as this will make things clearer and help you avoid callback hell, that Observable and Promises were supposed to help preventing in the first place.

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

Also, consider using switchMap instead of flatMap, basically it will allow to 'cancel' the other requests if the first one emits a new value. Nice to use if the first Observable that triggers the rest is some click event on a button, for instance.

如果你不需要你的各种请求轮流等待对方,你可以使用forkJoinzip一次性启动它们,见@Dan Macak 的回答,了解详情和其他见解.

If you don't need your various requests to wait in turn for each other, you can use forkJoin or zip to start them all at once, see @Dan Macak answer's for details and other insights.

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

Concerning Observables and Angular, you can perfectly use | async pipe in a Angular template instead of subscribing to the Observable in your component code, to get the value(s) emitted by this Observable

如果你不觉得直接使用 Observable,你可以简单地在你的 Observable 上使用 .toPromise(),然后是一些 async/await 指令.

if you're not feeling using Observable directly, you can simply use .toPromise() on your Observable, and then some async/await instructions.

如果您的 Observable 应该只返回一个结果(就像基本 API 调用的情况一样),则 Observable 可以被视为与 Promise 相当.

If your Observable is supposed to return only one result (as it is the case with basic API calls) , an Observable can be seen as quite equivalent to a Promise.

但是,考虑到 Observable 已经提供的所有内容,我不确定是否需要这样做(对读者来说:欢迎提供有启发性的反例!).我更倾向于尽可能使用 Observables 作为训练练习.

However, I'm not sure there is any need to do that, considering all the stuff that Observable already provide (to readers : enlightening counter-examples are welcome!) . I would be more in favor of using Observables whenever you can, as a training exercise.

一些有趣的博客文章(还有很多其他的):

Some interesting blog article on that (and there are plenty of others):

https://medium.com/@benlesh/rxjs-observable-interop-with-promises-and-async-await-bebb05306875

toPromise 函数实际上有点棘手,因为它不是真的是一个操作符",而是一个 RxJS 特定的方法订阅一个 Observable 并将其包装在一个承诺中.承诺将解析为 Observable 最后发出的值Observable 完成.这意味着如果 Observable 发出值hi"然后在完成前等待 10 秒,返回的promise 会等待 10 秒才能解析hi".如果可观察永远不会完成,那么 Promise 永远不会解决.

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.

注意:使用 toPromise() 是一种反模式,除非你是处理需要 Promise 的 API,例如 async-await

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

(强调我的)

顺便说一句,如果有人能给我一个示例代码来解决就好了这与异步/等待:D

BTW, it will be nice if anyone can give me an example code to solve this with async/await :D

例如,如果您真的想这样做(可能有一些错误,现在无法检查,请随时更正)

Example if you really want to do it (probably with some mistakes, can't check right now, please feel free to correct)

// 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 对 Observables 所做的那样)

In the case you can start all requests simultaneously, await Promise.all() which should be more efficient, because none of the calls depends on the result of each other. (as would forkJoin do with Observables)

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.
}

这篇关于将 Observable 与 async/await 一起使用是一个好习惯吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆