如何在Rx Observable上“等待”?


106

我希望能够等待观察,例如

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

天真的尝试会导致等待立即解决,并且不会阻止执行

编辑:我完整的预期用例的伪代码是:

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

我知道我可以将其他代码移到另一个单独的函数中并将其传递到订阅回调中,但是我希望能够避免这种情况。


您是否不能将其余代码(要等待源代码的代码)移到.subscribe()方法调用中?
StriplingWarrior 2015年

Answers:


131

您必须向作出承诺await。将可观察对象的下一个事件转换为承诺,然后等待。

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

编辑说明:该答案最初使用.take(1),但更改为使用.first(),这避免了Promise永远不会解决的问题,如果流在值到达之前结束了。


3
除了可以使用take(1)之外,还可以使用await observable.first().toPromise();吗?
2016年

14
@apricity如果完成时没有任何值,first()将导致拒绝,并 take(1)导致未完成的承诺。
Estus Flask

6
@apricity @AgentME实际上,在这种情况下take(1)也不应该使用first()。因为您期望发生一个完全相同的事件,所以应该使用single(),如果事件多于1,它将引发异常,而当事件不存在时不引发异常。如果不止一个,则您的代码/数据模型等中可能存在问题。如果不使用single,最终将随意选择返回的第一个项目,而不会警告有更多的项目。您必须谨慎对待上游数据源的谓词,以始终保持相同的顺序。
ntziolis

3
不要忘记导入:import 'rxjs/add/operator/first';
Stephanie

7
现在不赞成使用toPromise(),我们应该怎么做?
Jus10

26

可能必须是

await observable.first().toPromise();

正如之前的评论所指出的,当空的完整可观测值时,take(1)first()运算符之间存在实质性差异。

Observable.empty().first().toPromise()会导致拒绝,EmptyError因此可以进行相应处理,因为确实没有任何价值。

Observable.empty().take(1).toPromise()会带来undefined有价值的解决方案。


其实take(1)不会产生一个悬而未决的承诺。它将产生一个由解决的承诺undefined
Johan t Hart

感谢您的注意,这是正确的。我不确定发布内容为何有所不同,行为可能在某些时候发生了变化。
Estus Flask


4

如果toPromise已为您弃用,则可以使用,.pipe(take(1)).toPromise但是如您所见,此处未弃用。

因此,请按照以下说明使用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);
  });

异步/等待示例:

//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);

在这里阅读更多。

并请删除此错误的说法toPromise,即已弃用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.