【问题标题】:How do I make a new call to an api when a previous one finished successfully?当前一个成功完成时,如何对 api 进行新的调用?
【发布时间】:2020-11-26 23:07:08
【问题描述】:

我是 angular 和 rxjs 的新手,我有以下场景,在我不知道的 angular / rxjs 的上下文中,我需要在成功解析对 api 的调用后进行新调用怎么做

handler(): void {
  this.serviceNAme
    .createDirectory(this.path)
    .pipe(
      finalize(() => {
        this.someProperty = false;
      })
    )
    .subscribe(
      (data) => console.log(data),
      (error) => console.error(error.message)
    );
}

当之前的调用成功时,对 api 进行新调用的正确方法是什么?

【问题讨论】:

    标签: javascript angular rxjs


    【解决方案1】:

    我知道您有一个serviceOne 和一个serviceTwo。并且您想使用从serviceOne 检索到的数据调用serviceTwo

    使用 rxjs switchMap 您可以将一个 observable 通过管道传输到另一个。

        handler(): void {
            this.serviceOne
                .createDirectory(this.path)
                .pipe(
                    switchMap(serviceOneResult => {
                        // transform data as you wish
                        return this.serviceTwo.methodCall(serviceOneResult);
                    })
                )
                .subscribe({
                    next: serviceTwoResult => {
                        // here we have the data returned by serviceTwo
                    },
                    error: err => {},
                });
        }
    

    如果您不需要将数据从serviceOne 传递到serviceTwo,但您需要将它们一起完成,您可以使用rxjs forkJoin

        handler(): void {
            forkJoin([
                this.serviceOne.createDirectory(this.path), 
                this.serviceTwo.methodCall()
            ])
            .subscribe({
                next: ([serviceOneResult, serviceTwoResult]) => {
                    // here we have data returned by both services
                },
                error: err => {},
            });
        }
    

    【讨论】:

      【解决方案2】:

      使用aysncawait 你可以:

      async handler(): void {
        await this.serviceNAme
          .createDirectory(this.path)
          .pipe(
            finalize(() => {
              this.someProperty = false;
            })
          )
          .subscribe(
            (data) => console.log(data),
            (error) => console.error(error.message)
          );
      
         // Do second api call
      }
      

      【讨论】:

      • 感谢您的回答。如果第一个调用也失败了,第二个调用不会被执行吗?
      • 正确,除此之外,您还需要进行一些异常/错误处理,例如用 try { } catch {} 包装它。
      • 跟随asyncawait的行。在第一次调用中,无论响应是否成功,我都会处理最后我执行的操作,在asyncawait 的上下文中,我应该使用trycatchfinally
      【解决方案3】:

      有一些说法可以做到这一点:

      场景#1

      你的两个服务 api 调用是独立的,你只需要一个然后下一个

       const serviceCall1 = this.serviceName.createDirectory(this.path);
       const serviceCall2 = this.serviceName.createDirectory(this.otherPath);
      
       concat(serviceCall1 , serviceCall2).subscribe({
         next: console.log,
         error: err => console.error(err.message),
         complete: () => console.log("service call 1&2 complete")
       });
      

      场景#2

      您的两个调用相互依赖,因此您需要第一个调用的结果才能开始第二个调用

       this.serviceName.getDirectoryRoot().pipe(
         switchMap(root => this.serviceName.createDirectoryInRoot(root, this.path))
       ).subscribe({
         next: console.log,
         error: err => console.error(err.message),
         complete: () => console.log("service call 1 used to create service call 2, which is complete")
       });
      

      您需要场景#2,因为这样做,第一次调用中的错误将意味着没有结果发送到switchMap,并且永远不会进行第二次调用。 p>

      【讨论】:

      • 感谢您的回答。确实,第一种情况适用于我的情况,我很遗憾没有在问题中对此发表评论。我唯一没有看到的是,在我的情况下,我需要对每次调用 api 返回的数据执行操作,我看到下一个,是下一个吗?
      • @Mario, Mrk Sef 包含订阅的结果。你可以使用subscribe((res)=>{console.log(res)},(error)=>{console.log('an error')},(complete)=>{console.log("the observable is completed")})
      • @Mario - 是的,next completeerror 是被调用的回调函数。在这里,我只使用了console.log,但您可以将它们定义为您想要的任何东西。如果您想要更细粒度的控制,还可以单独更改服务调用 .pipe(map(...),tap(...))
      猜你喜欢
      • 2021-11-15
      • 2012-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-28
      • 2022-10-12
      • 2022-08-16
      • 1970-01-01
      相关资源
      最近更新 更多