【问题标题】:Two or more sequential requests inside another (Angular)另一个(Angular)内部的两个或多个顺序请求
【发布时间】:2019-11-10 13:56:32
【问题描述】:

我正在学习 rxjs,目前正在尝试弄清楚如何正确地发出一系列请求。 例如,UserService 其方法之一通过用户 ID 返回用户对象。比方说,在获得对象后,我想利用它包含的信息并发出一些帖子请求,如下所示:

    this.userService.getUser(5).subscribe(
      user => this.userService.sendEmail(this.makeEmailMessage(user.id, user.name, user.email)).pipe(
        delay(1000),
        tap(() => console.log('Sending an email'))
      ).subscribe(
        () => this.userService.sendSMS(this.makeSMSMessage(user.id, user.name, user.phone)).subscribe(
          () => console.log('Sending sms')
        )
      )
    );

但它有很多嵌套订阅,如果涉及更多请求,可能会变得不可读和难以管理。

上面的代码可以通过以下方式重写:

    this.userService.getUser(5).pipe(
      switchMap(
        user => {
          return forkJoin(
            this.userService.sendEmail(this.makeEmailMessage(user.id, user.name, user.email)).pipe(
              delay(1000),
              tap(() => console.log('Sending a email.'))
            ),
            this.userService.sendSMS(this.makeSMSMessage(user.id, user.name, user.phone)).pipe(
              tap(() => console.log('Sending an sms'))
            )
          );
        }
      )
    ).subscribe(
      res => console.log(res)
    );

forkJoin 操作符保持请求的顺序,但短信将首先完成。如果请求顺序无关紧要,那么我认为该代码是可以的,但是如果要求保持顺序呢。

无论如何,我想知道的是,当请求顺序很重要和不重要时,处理此类构造的最佳方法是什么。另外,说到错误处理,我认为正确的方法是使用管道内的catchError 运算符(我使用tap)来处理它。对吗?

【问题讨论】:

    标签: angular typescript


    【解决方案1】:

    如果电子邮件和短信的顺序对您很重要,那么您可以使用switchMap 运算符对 HTTP 调用进行排序

       this.userService
          .getUser(5)
          // If error retrieving user, go straight to error block inside subscribe
          // no email, sms, push notification will be sent
          .pipe(
            switchMap(user => {
              return this.userService
                .sendEmail(this.makeEmailMessage(user.id, user.name, user.email))
                .pipe(
                  // catchError((err, obs) => of({})) == if you wish to send SMS and Push notification even if sending email failed
                  delay(1000),
                  switchMap(() =>
                    this.userService.sendSMS(
                      this.makeSMSMessage(user.id, user.name, user.phone)
                    )
                    // .pipe(catchError((error, obs) => of({})) if you wish to send Push notification even if sending SMS failed
                  ),
                  switchMap(() =>
                    // Push Notification will occur last
                    this.userService.sendPushNotification(
                      this.makePushNotificationMessage(
                        user.id,
                        user.name,
                        user.phone
                      )
                    )
                  )
                );
            })
          )
          .subscribe({
            next: next => {
              console.log(next);
            },
            error: error => {
              console.error(error);
            }
          });
    

    通常,我们在使用catchError() 运算符时应该非常小心,因为天真地使用它会抑制错误消息并使应用程序更难排除故障。 catchError 应该在内部将消息记录到控制台或某个日志系统,以便我们知道我们跳过了一个异常。

    【讨论】:

      猜你喜欢
      • 2013-12-18
      • 1970-01-01
      • 2013-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多