简体   繁体   English

我如何在 Rx Observable 上“等待”?

[英]How can I `await` on an Rx Observable?

I'd like to be able to await on an observable, eg我希望能够等待一个可观察的对象,例如

const source = Rx.Observable.create(/* ... */)
//...
await source;

A naive attempt results in the await resolving immediately and not blocking execution天真的尝试导致等待立即解决而不是阻止执行

Edit: The pseudocode for my full intended use case is:编辑:我的完整预期用例的伪代码是:

if (condition) {
  await observable;
}
// a bunch of other code

I understand that I can move the other code into another separate function and pass it into the subscribe callback, but I'm hoping to be able to avoid that.我知道我可以将其他代码移动到另一个单独的函数中并将其传递给订阅回调,但我希望能够避免这种情况。

You have to pass a promise to await .你必须通过一个 promise 来await Convert the observable's next event to a promise and await that.将 observable 的下一个事件转换为 promise 并等待它。

if (condition) {
  await observable.first().toPromise();
}

Edit note: This answer originally used .take(1) but was changed to use .first() which avoids the issue of the Promise never resolving if the stream ends before a value comes through.编辑说明:此答案最初使用 .take(1) 但已更改为使用 .first() 这避免了如果流在值通过之前结束则无法解决 Promise 的问题。

As of RxJS v8, toPromise will be removed.从 RxJS v8 开始, toPromise将被移除。 Instead, the above can be replaced with await firstValueFrom(observable)相反,上面可以替换为await firstValueFrom(observable)

It likely has to be它可能必须是

await observable.first().toPromise();

As it was noted in comments before, there is substantial difference between take(1) and first() operators when there is empty completed observable.正如之前评论中所指出的,当有空的已完成 observable 时, take(1)first()运算符之间存在重大差异。

Observable.empty().first().toPromise() will result in rejection with EmptyError that can be handled accordingly, because there really was no value. Observable.empty().first().toPromise()将导致拒绝EmptyError可以相应地处理,因为确实没有价值。

And Observable.empty().take(1).toPromise() will result in resolution with undefined value. Observable.empty().take(1).toPromise()将导致解析值undefined

Use the new firstValueFrom() or lastValueFrom() instead of toPromise() , which as pointed out here, is deprecated starting in RxJS 7, and will be removed in RxJS 8.使用新的firstValueFrom()lastValueFrom()而不是toPromise() ,正如这里指出的那样,从 RxJS 7 开始不推荐使用,并将在 RxJS 8 中删除。

import { firstValueFrom} from 'rxjs';
import { lastValueFrom } from 'rxjs';

this.myProp = await firstValueFrom(myObservable$);
this.myProp = await lastValueFrom(myObservable$);

This is available in RxJS 7+这在 RxJS 7+ 中可用

See: https://indepth.dev/rxjs-heads-up-topromise-is-being-deprecated/请参阅: https : //indepth.dev/rxjs-heads-up-topromise-is-being-deprecated/

You will need to await a promise, so you will want to use toPromise() .您将需要await承诺,因此您需要使用toPromise() See this for more details on toPromise() .为更多细节toPromise()

If toPromise is deprecated for you, you can use .pipe(take(1)).toPromise but as you can see here it's not deprecated.如果toPromise已为您弃用,您可以使用.pipe(take(1)).toPromise但正如您在此处看到的那样它并未被弃用。

So please juste use toPromise (RxJs 6) as said:所以请使用toPromise (RxJs 6) 说:

//return basic observable
const sample = val => Rx.Observable.of(val).delay(5000);
//convert basic observable to promise
const example = sample('First Example')
  .toPromise()
  //output: 'First Example'
  .then(result => {
    console.log('From Promise:', result);
  });

async/await example:异步/等待示例:

//return basic observable
const sample = val => Rx.Observable.of(val).delay(5000);
//convert basic observable to promise
const example = await sample('First Example').toPromise()
// output: 'First Example'
console.log('From Promise:', result);

Read more here .在这里阅读更多。

And please remove this wrong claim saying toPromise is deprecated.并且请删除这个错误的声明,说toPromise已被弃用。

Using toPromise() is not recommended as it is getting depreciated in RxJs 7 onwards.不推荐使用toPromise()因为它在 RxJs 7 之后会贬值。 You can use two new operators present in RxJs 7 lastValueFrom() and firstValueFrom() .您可以使用 RxJs 7 lastValueFrom()firstValueFrom()存在的两个新运算符。 More details can be found here可以在此处找到更多详细信息

const result = await lastValueFrom(myObservable$);

Implementations in Beta version are available here: Beta 版的实现可在此处获得:

I am using RxJS V 6.4.0, hence I should use deprecated one in V 7.xx toPromise() .我使用的是 RxJS V 6.4.0,因此我应该使用 V 7.xx toPromise()已弃用的一个。 Inspired by other answers, here is what I did with toPromise()受到其他答案的启发,这是我对toPromise()所做的

import { first, ... } from 'rxjs/operators';

...

if (condition) {
  await observable$.pipe(first()).toPromise();
}

...

Note how I used last() inside a pipe() .请注意我如何在pipe()使用last() pipe() Because on mine observable.first() does not works just like mentioned by macil因为在我的observable.first()上不像macil提到的那样工作

Hope this helps others who using RxJS V 6.xx as I do :).希望这可以帮助像我一样使用 RxJS V 6.xx 的其他人:)。

Thanks.谢谢。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM