如何在Rx Observable上"等待"?

Che*_*aks 83 javascript rxjs ecmascript-7

我希望能够等待一个可观察的,例如

const source = Rx.Observable.create(/* ... */)
//...
await source;
Run Code Online (Sandbox Code Playgroud)

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

编辑:我的完整用途的伪代码是:

if (condition) {
  await observable;
}
// a bunch of other code
Run Code Online (Sandbox Code Playgroud)

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

Mac*_*cil 106

你必须通过承诺await.将observable的下一个事件转换为promise并等待它.

if (condition) {
  await observable.first().toPromise();
}
Run Code Online (Sandbox Code Playgroud)

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

  • @apricity如果完成时没有值,`first()`将导致拒绝,`take(1)`将导致未决的承诺. (12认同)
  • 现在不推荐使用toPromise(),我们应该怎么做? (7认同)
  • @apricity @AgentME实际上你不应该在这种情况下使用`take(1)`或`first()`.由于您期望恰好发生一个事件,因此您应该使用`single()`,如果超过1则抛出异常,而在没有异常时抛出异常.如果存在多个,则代码/数据模型中可能存在错误.如果您不使用单个,则最终会随意选择返回的第一个项目,而不会发出警告.您必须注意上游数据源中的谓词,以始终保持相同的顺序. (4认同)
  • 你可以使用`await observable.first().toPromise();而不是take(1). (3认同)
  • 不要忘记导入:`import'rxjs/add/operator/first';` (3认同)
  • 使用新的“firstValueFrom()”或“lastValueFrom()”代替 toPromise。在 RxJS 7+ 中可用。请参阅:https://indepth.dev/rxjs-heads-up-topromise-is-being-deprecated/ (3认同)
  • @ Jus10我找不到任何东西来表明`toPromise()`已被弃用。你在哪里读的? (2认同)
  • @EstusFlask 实际上 `take(1)` 不会产生待处理的承诺。它将产生一个用“undefined”解决的承诺。 (2认同)
  • 也许它以前有效,但现在需要 `pipe`:`observable.pipe(first()).toPromise()`。 (2认同)

Est*_*ask 23

它一定要是

await observable.first().toPromise();
Run Code Online (Sandbox Code Playgroud)

正如之前的评论中所指出的那样,当存在空的完整观察值时take(1),first()运算符与运算符之间存在很大差异.

Observable.empty().first().toPromise()将导致拒绝,EmptyError因此可以相应地处理,这通常是理想的行为.

并且Observable.empty().take(1).toPromise()将导致未决的承诺,这是可取的......几乎从不.


Tet*_*Dev 20

使用新的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$);
Run Code Online (Sandbox Code Playgroud)

这在 RxJS 7+ 中可用

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


Cur*_*rse 9

如果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);
  });
Run Code Online (Sandbox Code Playgroud)

异步/等待示例:

//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);
Run Code Online (Sandbox Code Playgroud)

在这里阅读更多。

并请删除这个错误的声明说toPromise已弃用。


Jos*_*ham 8

你需要await一个承诺,所以你会想要使用toPromise().见对更多的细节toPromise().


Ani*_*ert 5

toPromise()不建议使用,因为它从 RxJs 7 开始逐渐贬值。您可以使用 RxJs 7lastValueFrom()和中存在的两个新运算符firstValueFrom()更多详情可在这找到

const result = await lastValueFrom(myObservable$);
Run Code Online (Sandbox Code Playgroud)

Beta 版本的实现可在此处获取: