Angular 另一个内部的两个或多个连续请求(角度)

Angular 另一个内部的两个或多个连续请求(角度),angular,typescript,Angular,Typescript,我正在学习rxjs,目前正试图找出如何正确地发出一系列请求。 例如,有一个UserService,它的一个方法通过用户id返回一个用户对象。比如说,在获取对象后,我想利用它包含的信息,并发出一些post请求,如下所示: this.userService.getUser(5).subscribe( user => this.userService.sendEmail(this.makeEmailMessage(user.id, user.name, user.email)

我正在学习rxjs,目前正试图找出如何正确地发出一系列请求。 例如,有一个
UserService
,它的一个方法通过用户id返回一个用户对象。比如说,在获取对象后,我想利用它包含的信息,并发出一些post请求,如下所示:

    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
操作员保留请求的顺序,但sms将首先完成。如果请求顺序无关紧要,那么我认为代码是可以的,但是如果需求是保持顺序呢


无论如何,我想知道的是,当请求顺序重要时,以及当请求顺序不重要时,处理此类构造的最佳方法是什么。另外,说到错误处理,我认为正确的方法应该是在管道中使用
catchError
操作符来处理它(在这里我使用了
tap
)。是否正确?

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

this.userService
.getUser(5)
//如果检索用户时出错,请直接转到订阅中的错误块
//不会发送电子邮件、短信和推送通知
.烟斗(
开关映射(用户=>{
返回此.userService
.sendmail(此.makeEmailMessage(user.id、user.name、user.email))
.烟斗(
//catchError((err,obs)=>of({}))==如果您希望发送短信息和推送通知,即使发送电子邮件失败
延迟(1000),
开关映射(()=>
此文件为.userService.sendSMS(
this.makesmessage(user.id、user.name、user.phone)
)
//.pipe(catchError((error,obs)=>of({}))如果您希望发送推送通知,即使发送SMS失败
),
开关映射(()=>
//推送通知将在最后发生
this.userService.sendPushNotification(
此消息为.makePushNotificationMessage(
user.id,
user.name,
用户电话
)
)
)
);
})
)
.订阅({
下一步:下一步=>{
console.log(下一步);
},
错误:错误=>{
控制台错误(error);
}
});
通常,我们在使用
catchError()
操作符时应该非常小心,因为单纯地使用它会抑制错误消息,使应用程序更难进行故障排除。
catchError
应该在内部将消息记录到控制台或某个日志系统,以便我们知道跳过了异常