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

Angular 有条件地执行switchMap,否则,取消所有操作而不触发错误事件,angular,typescript,rxjs,Angular,Typescript,Rxjs,我正在用Angular 10做一个web应用程序。我试着用可观察的而不是承诺来工作,但有时很难建立一个执行流程 我想完成这个流程: 呈现确认模式 如果确认有一个值({isConfirmed:true}),则表示加载(条件如下) 执行switchMap以开始执行HTTP调用 如果任何HTTP调用失败,则隐藏加载并显示警告消息 逻辑: send(title: string, message): Observable<any> { const isConfirmed: Prom

我正在用Angular 10做一个web应用程序。我试着用可观察的而不是承诺来工作,但有时很难建立一个执行流程

我想完成这个流程:

  • 呈现确认模式
  • 如果确认有一个值(
    {isConfirmed:true}
    ),则表示加载(条件如下)
  • 执行
    switchMap
    以开始执行HTTP调用
  • 如果任何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.')
            })
          );
      }
    
    send(标题:字符串,消息):可观察{
    const isconfirm:Promise=this.alertService.warningConfirmation(
    “发送消息”,
    '您确定要发送此消息吗?',
    “发送”,
    “取消”
    );
    从返回(已确认)
    .烟斗(
    点击(res=>res.isconfirm?this.loadingService.present():EMPTY),
    switchMap(res=>from(this.service.httpCallOneGetUsers())
    .烟斗(
    map(users=>users.map(user=>user.email)),
    switchMap(emails=>this.service.httpCallTwoSendMessage(标题、消息、电子邮件))
    )
    ),
    完成(()=>this.loadingService.disclose()),
    水龙头({
    下一步:()=>console.log('messagesent!'),
    错误:()=>console.log('无法发送消息')
    })
    );
    }
    
    当我取消确认时,将触发错误事件。此外,荷载从未显示

    我在第一个
    switchMap
    中有两个HTTP调用,两个调用都可能失败,一个返回承诺,另一个返回可观察的。这就是为什么我在
    from()
    中添加了第一个HTTP调用

    我的目标是:

  • 如果确认结果为
    isConfirmed:true
    ,则有条件地执行/输入
    开关映射。否则,取消所有并退出逻辑,而不触发错误事件
  • 其中是添加
    点击
    完成
    以隐藏加载并向用户显示成功/错误消息的最佳位置

  • 我想你可以这样做:

    return from(isConfirmed)
        .pipe(
            switchMap(res => res.isConfirmed ? of(res) : EMPTY),
            tap(() => this.loadingService.present()),
            switchMap(res => from(this.service.httpCallOneGetUsers()).pipe(...)
            ...
    
    唯一的变化是,我在开始时使用了
    switchMap
    tap()
    。如果
    res.isconfirm===false
    则重新输入
    EMPTY
    ,这将不会触发以下任何运算符(它只是一个
    完成的
    通知)。当它为
    true
    时,我将返回原始
    res
    对象,其中包含
    of(res)


    要隐藏加载,最好的操作符很可能是
    finalize()
    ,因为它是在链被释放时触发的,即在链完成、出错或取消订阅之后。

    我认为您可以按以下方式执行:

    return from(isConfirmed)
        .pipe(
            switchMap(res => res.isConfirmed ? of(res) : EMPTY),
            tap(() => this.loadingService.present()),
            switchMap(res => from(this.service.httpCallOneGetUsers()).pipe(...)
            ...
    
    唯一的变化是,我在开始时使用了
    switchMap
    tap()
    。如果
    res.isconfirm===false
    则重新输入
    EMPTY
    ,这将不会触发以下任何运算符(它只是一个
    完成的
    通知)。当它为
    true
    时,我将返回原始
    res
    对象,其中包含
    of(res)

    要隐藏加载,最好的操作符很可能是
    finalize()
    ,因为它是在链完成、出错或取消订阅后被释放时触发的。

    1 如果确认结果为
    isConfirmed:true
    ,则有条件地执行/输入
    开关映射

    试试看。例如:

    来自(已确认)。管道(
    过滤器((res)=>!!res.isconfirm)
    ...
    )
    
    这将仅发出与过滤条件匹配的值

    2. 哪里是添加分接或最终确定的最佳位置

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

    • 点击
      :无论您想在哪里执行某些操作。例如,如果您想向用户打印电子邮件,则需要将
      tap
      指令放在管道中包含该数据的部分


    总结:

    来自(已确认)。管道(
    过滤器((res)=>!!res.isconfirm),
    switchMap((res)=>from(this.service.httpCallOneGetUsers()),
    map((用户)=>users.map((用户)=>user.email)),
    开关映射((电子邮件)=>
    this.service.httpCallTwoSendMessage(标题、消息、电子邮件)
    ),
    完成(()=>this.loadingService.disclose()),
    水龙头({
    下一步:()=>console.log(“消息已发送!”),
    错误:()=>console.log(“无法发送消息”),
    })
    );
    
    注意:最后一个
    点击
    就像订阅结果的接收者,这就是为什么它是最后一个。但是该代码应该放在
    订阅

    更新(来自评论) 若要在不满足条件时最终确定可观测值,应执行以下操作:

    来自(已确认)。管道(
    开关图((分辨率)=>{
    如果(决议已确认){
    this.loadingService.present();
    从(this.service.httpCallOneGetUsers())返回;
    }否则{
    投掷者(“”);
    }
    }),
    map((用户)=>users.map((用户)=>user.email)),
    开关映射((电子邮件)=>
    this.service.httpCallTwoSendMessage(标题、消息、电子邮件)
    ),
    完成(()=>this.loadingService.disclose()),
    水龙头({
    下一步:()=>console.log(“消息已发送!”),
    错误:()=>console.log(“无法发送消息”),
    })
    );
    
    如果条件为true,管道将按预期顺序执行。如果条件为false,则从第一个
    开关映射
    跳到
    完成

    1 如果确认结果为
    isConfirmed:true
    ,则有条件地执行/输入
    开关映射

    试试看。例如:

    来自(已确认)。管道(
    过滤器((res)=>!!res.isconfirm)
    ...
    )
    
    这将仅发出与过滤条件匹配的值

    2. 哪里是添加抽头或定稿的最佳位置