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

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

问题描述

我正在使用角度2公共http返回一个Observable,但是当我使用嵌套的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

推荐答案

按顺序束缚Observable,就像您想在代码中所做的那样

关于您的代码示例,如果要链接Observables(在前一个发射之后触发另一个),请使用flatMap(或switchMap)来实现此目的:

Chaining Observables in sequence, as you want to do in your code

Concerning your code example, if you want to chain Observables (trigger another after the previous emits), use flatMap (or switchMap) for this purpose :

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

与嵌套相比,这是一种更好的做法,因为它可以使事情变得更清楚,并帮助您避免回调地狱,而Observable和Promises最初应该可以帮助防止这种情况.

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是按钮上的某些click事件,则很好用.

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一次启动所有请求,请参见

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.

关于Observable和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(),然后再使用一些异步/等待指令即可.

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并将其包装在一个Promise中. 诺言 一旦 可观察的完成.这意味着如果Observable发出 值"hi"然后等待10秒钟才完成,返回 许诺将等待10秒钟才能解决"hi".如果可观察 永远不会完成,那么承诺永远不会解决.

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

(重点是我的)

顺便说一句,如果有人可以给我示例代码来解决,那就太好了 这与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 promises results,
    // res[0], res[1], res[2] respectively.
}

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

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