【问题标题】:How to make two api calls using Promise.all within Angular9?如何在 Angular 9 中使用 Promise.all 进行两次 api 调用?
【发布时间】:2020-12-16 23:13:04
【问题描述】:

我使用 Promise.all 进行 api 调用,如下所示:

    Promise.all(this.hostName.slice(0, this.Id.length).map((hostName) => {
        return this.serviceC.status(hostName)
            .then(res => {
                return new Promise((resolve, reject) => {
                    const oretry: ORInterface = {
                        oQid: res.rows[0].qid,
                        reason: this.reason
                    };
                    this.serviceB.retry(oretry).subscribe(resolve);
                });
            });
    }))
.then(() => {
        this.dialog.close();
    })
        .catch(err => {
            console.log(err);
        });

上面的代码工作正常。 现在我想在成功完成this.serviceB.retry(oretry) 之后再进行一次api调用。 第二个api是this.serviceB.createDbEntry(sentry)sentry如下:

                    const sretry: SDInterface = {
                        hostName,
                        Id: this.Id.slice(0, this.Id.length),
                        reason: this.reason
                    };

而且,我正在这样做

    Promise.all(this.hostName.slice(0, this.Id.length).map((hostName) => {
        return this.serviceC.status(hostName)
            .then(res => {
                return new Promise((resolve, reject) => {
                    const oretry: ORInterface = {
                        oQid: res.rows[0].qid,
                        reason: this.reason
                    };
                    const sretry: SDInterface = {
                        hostName,
                        Id: this.Id.slice(0, this.Id.length),
                        reason: this.reason
                    };
                    this.serviceB.retry(oretry).subscribe(resolve);
                    this.serviceB.createDbEntry(sentry).subscribe(resolve);
                });
            });
    }))
.then(() => {
        this.dialog.close();
    })
        .catch(err => {
            console.log(err);
        });

以上代码报错:

error: "SequelizeValidationError: string violation: Id cannot be an array or an object"

看起来它没有为每个Id调用第二个api

【问题讨论】:

    标签: javascript node.js angular promise angular-promise


    【解决方案1】:

    promise.all 在数组中接受输入并在数组中给出响应,

    创建 2 个函数,每个函数都使用异步逻辑返回一个承诺,

    说funcA和funcB,然后用下面来并行调用它们

    Promise.all([funcA(this.hostName), funcB(this.id)])
        .then(respones => {
            console.log(responses[0]); //return value for funcA
            console.log(responses[1]); //return value for funcB
        })
        .catch(err => console.log(err));
    

    我假设你的函数逻辑是正确的,我只是从你的问题中复制粘贴并给了它们结构

    const funcA = (hostName) => {
    hostName.slice(0, this.Id.length).map((hostName) => {
        return this.serviceC.status(hostName)
            .then(res => {
                return new Promise((resolve, reject) => {
                    const oretry: ORInterface = {
                        oQid: res.rows[0].qid,
                        reason: this.reason
                    };
                    this.serviceB.retry(oretry).subscribe(resolve);
                });
            });
        });
    }
    
    
    const funcB = (Id) => {
    Id.slice(0, this.Id.length).map(id => {
                    return new Promise((resolve, reject) => {
                        const sretry: SDInterface = {
                            hostName,
                            Id: id,
                            reason: this.reason
                        };
    
                        this.serviceB.createDbEntry(sentry).subscribe(resolve);
                    });
                })
    }
    

    【讨论】:

    • 您能否更新您的答案并展示如何在funcA 中使用this.hostName.slice(0, this.Id.length) 并在funcB 中使用this.Id.slice(0, this.Id.length)
    • funcB 抛出错误TS2663: Cannot find name 'hostName'. Did you mean the instance member 'this.hostName'?
    • 如何将hostNamefuncA传递到funcB
    • funcB 仍然抛出错误TS2304: Cannot find name 'hostName
    【解决方案2】:

    你可能想看看forkJoin

    import { Observable, forkJoin } from 'rxjs';
    

    然后

    ngOnInit() {
        let one = this.http.get('some/api/1') //some observable;
        let two = this.http.get('some/api/2') // another observable;
    
        forkJoin([one, tow]).subscribe(response => {
         // results[0] is our one call
         // results[1] is our second call
         let var1 = response[1];
         let var2 = response[0];
        }/*, error => { in case error handler } */); 
    }
    

    【讨论】:

      【解决方案3】:

      再次使用Promise.all()不是更好吗?

      Promise.all(this.hostName.slice(0, this.Id.length).map((hostName) => {
          return this.serviceC.status(hostName)
              .then(res => {
                  return new Promise((resolve, reject) => {
                      const oretry: ORInterface = {
                          oQid: res.rows[0].qid,
                          reason: this.reason
                      };
                      this.serviceB.retry(oretry).subscribe(resolve);
                  });
              })
              .then(() => {
                  return Promise.all(this.Id.slice(0, this.Id.length).map(id => {
                      return new Promise((resolve, reject) => {
                          const sretry: SDInterface = {
                              hostName,
                              Id: id,
                              reason: this.reason
                          };
      
                          this.serviceB.createDbEntry(sentry).subscribe(resolve);
                      });
                  })
              });
      }))
          .then(() => {
              this.dialog.close();
          })
          .catch(err => {
              console.log(err);
          });
      
      

      而使用toPromise()会使代码更加简洁。

      Promise.all(this.hostName.slice(0, this.Id.length).map((hostName) => {
          return this.serviceC.status(hostName)
              .then(res => {
                  const oretry: ORInterface = {
                      oQid: res.rows[0].qid,
                      reason: this.reason
                  };
                  return this.serviceB.retry(oretry).toPromise();
              })
              .then(() => {
                  return Promise.all(this.Id.slice(0, this.Id.length).map(id => {
                      const sretry: SDInterface = {
                          hostName,
                          Id: id,
                          reason: this.reason
                      };
      
                      this.serviceB.createDbEntry(sentry).toPromise();
                  })
              });
      }))
          .then(() => {
              this.dialog.close();
          })
          .catch(err => {
              console.log(err);
          });
      
      

      【讨论】:

      • 我正在尝试使用toPromise(),但收到错误TSLint: Missing semicolon(semicolon)
      • 再添加一个括号...this.serviceB.createDbEntry(sentry).toPromise(); })); });,分号错误就消失了。请注意,nowthis.serviceB.createDbEntry(sentry).toPromise(); 运行了两次而不是一次。你能查一下吗?
      【解决方案4】:

      使用 combineLatest,在 Angular 中我们使用 RxJs 而不是 Promise。

      combineLatest(
        [this.http.get('call1'), this.http.get('call2')]
      ).subscribe(([result1, result2]) => {
        // do stuff with result1 and result2
      });
      

      【讨论】:

      • 我依赖于promise。我可以使用上述答案中的toPromise() 使其工作。唯一的问题是this.serviceB.createDbEntry(sentry).toPromise(); 运行了两次而不是一次。你能查一下吗?
      猜你喜欢
      • 2020-12-16
      • 2020-06-07
      • 2020-09-22
      • 1970-01-01
      • 2021-06-06
      • 2020-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多