合并两个可观察对象,但要等到第一个完成时才触发第二个

时间:2020-02-27 18:18:54

标签: angular rxjs

我有两个模式对话框,选择和确认。这是工作代码:

this.newClientId.pipe(take(1)).subscribe(
    response => this.confirmDialogService.ask('DSf').pipe(take(1)).subscribe(
        answer => answer ? this.createOrder(response) : this.goBack.next()
    )
);

“选择”对话框将值放入newClientId中,然后触发确认对话框,当用户确认创建后便创建了新订单。

有没有嵌套的可能吗?

在这里找到的所有建议都会在设置newClientID之前触发确认对话框。

3 个答案:

答案 0 :(得分:1)

我认为可以使用switchMap运算符来完成,一旦一个发射器就切换到一个新的可观测的物体。

尝试:

this.newClientId.pipe(
 take(1),
 switchMap(response => {
   return [of(response), this.confirmDialogService.ask('DSf')];
 }
 take(1),
).subscribe(([response, answer])=> answer ? this.createOrder(response) : this.goBack.next());

答案 1 :(得分:0)

合并内部和外部可观察的值:

要合并内部和外部可观察值,可以使用switchMap rxjs运算符。

this.newClientId
  .pipe(
    take(1),
    switchMap(
      clientId => this.confirmDialogService.ask('DSf'),
      (clientId, answer) => [clientId, answer]
    )
  )
  .subscribe(([clientId, answer]) => {
    console.log(`Received client id is: ${clientId} and confirmation from user is: ${answer}`);
    // Perform your logic now
  });

switchMap运算符有多个替代版本,而我已经展示了具有 selector函数的版本(请仔细查看运算符的第二个参数)。通常,如果省略选择器函数,则仅返回内部可观察的值。您可以使用选择器功能自定义输出,以将外部和内部可观测值的值合并到一个数组中,如上例所示。

检查一下我为您在栈闪电战中为用例创建的demo rxjs app

有关switchMap和switchMap中的选择器功能的更多信息,请参阅此article。如果您是第一次使用switchMap运算符,我强烈建议您阅读本文。

替代方法:

从您的代码片段中,我了解到您只对可观察对象的第一个值感兴趣。在这种情况下,您可以使用Promises和ES6 async-await语法,而不是合并可观察变量,以提供一种优雅且简单的解决方案。

使用Promises和async-await,您可以按以下方式更改代码段:

async getResult() {
  let clientId = await this.newClientId.toPromise();
  let answer = await this.confirmDialogService.ask('DSf'),toPromise();
  // perform your logic
}

在上面的代码段中,confirmDialogService.ask()将不被调用,直到newClientId返回结果。因此,异步调用现在是同步进行的,并且只有在完成2个异步调用(按指定的顺序)之后,它才会执行方法中的其余代码。

编辑:更新了答案,以使用rxjs运算符解决问题。

答案 2 :(得分:0)

有一种简单的方法可以将两个Observable与rx.zip运算符组合在一起,以避免嵌套订阅

Display()

您能解释一下,为什么在两种情况下都使用“ pipe(take(1))”吗?也许这会改变我的答案。

clientId是Observable还是BehaviourSubject?