Warm tip: This article is reproduced from serverfault.com, please click

angular-有条件地执行switchMap,否则,取消所有操作而不触发错误事件

(angular - Conditionally execute the switchMap, otherwise, cancel all without firing the error event)

发布于 2020-12-01 14:22:11

我正在Angular 10中做一个Web应用程序。我尝试继续使用Observables而不是Promises,但是有时很难建立执行流程。

我想完成以下流程:

  1. 提出确认模式
  2. 如果确认中包含一个值({isConfirmed: true}),则显示一个载荷(此处是条件)。
  3. 执行switchMap以开始执行HTTP调用。
  4. 如果任何HTTP调用失败,请隐藏加载并显示警告消息

逻辑:

  send(title: string, message): Observable<any> {
    const isConfirmed: Promise<{isConfirmed: boolean}> = this.alertService.warningConfirmation(
      'Send message',
      'Are you sure you want to send the message?',
      'Send',
      'Cancel'
    );

    return from(isConfirmed)
      .pipe(
        tap(res => res.isConfirmed ? this.loadingService.present() : EMPTY),
        switchMap(res => from(this.service.httpCallOneGetUsers())
          .pipe(
            map(users => users.map(user => user.email)),
            switchMap(emails => this.service.httpCallTwoSendMessage(title, message, emails))
          )
        ),
        finalize(() => this.loadingService.dismiss()),
        tap({
          next: () => console.log('Message sent!'),
          error: () => console.log('Could not send the message.')
        })
      );
  }

当我取消确认时,会触发错误事件。而且,永远不会显示加载。

我在第一个内部有2个HTTP调用switchMap,两个都可能失败,一个返回Promise,另一个返回Observable。这就是为什么我在中添加了第一个HTTP调用的原因from()

我的目标是:

  1. switchMap如果确认结果为有条件执行/输入isConfirmed: true否则,请取消所有操作并退出逻辑而不会引发错误事件。
  2. 在的最佳位置是添加tapfinalize隐藏负载并向用户显示成功/错误消息的最佳位置
Questioner
RRGT19
Viewed
0
adrisons 2020-12-02 17:28:07

1个

switchMap如果确认结果为有条件执行/输入isConfirmed: true

尝试一下filter例如:

from(isConfirmed).pipe(
  filter((res) => !!res.isConfirmed)
  ...
)

这只会发出与过滤条件匹配的值。

2个

添加水龙头或敲定的完美位置在哪里?

  • finalize:最后,因此,如果任何订阅在订阅之前失败,则将执行该订阅。

  • tap:无论你要执行什么操作。例如,如果要打印用户o电子邮件,则需要将tap说明放在管道中具有该数据的部分中。


总结:

from(isConfirmed).pipe(
  filter((res) => !!res.isConfirmed),
  switchMap((res) => from(this.service.httpCallOneGetUsers())),
  map((users) => users.map((user) => user.email)),
  switchMap((emails) =>
    this.service.httpCallTwoSendMessage(title, message, emails)
  ),
  finalize(() => this.loadingService.dismiss()),
  tap({
    next: () => console.log("Message sent!"),
    error: () => console.log("Could not send the message."),
  })
);

注意:last的tap行为类似于订阅结果的接收者,这就是为什么last的原因。但是该代码应该放在中subscribe

更新(来自评论)

要在不满足条件时最终确定 Observable 对象,你应该执行以下操作:

from(isConfirmed).pipe(
  switchMap((res) => {
    if (res.isConfirmed) {
      this.loadingService.present();
      return from(this.service.httpCallOneGetUsers());
    } else {
      throwError("");
    }
  }),
  map((users) => users.map((user) => user.email)),
  switchMap((emails) =>
    this.service.httpCallTwoSendMessage(title, message, emails)
  ),
  finalize(() => this.loadingService.dismiss()),
  tap({
    next: () => console.log("Message sent!"),
    error: () => console.log("Could not send the message."),
  })
);

如果条件为真,则管道将按预期顺序执行。如果条件为假,则从第一个条件switchMap跳到finalize