【问题标题】:Calling multiple api's at the same time同时调用多个api
【发布时间】:2020-11-05 21:51:13
【问题描述】:

我正在尝试调用两个API,但它们一个接一个地被调用,因此我在不必要地浪费时间。如何同时调用两者并帮助我节省时间。

this.data = await this.processService.workflowAPI1('activiti$requisitionandpo', 'COMPLETED').then((d: any) => {
      return d;
    })

this.APIresponse = await this.processService.workflowAPI(selected_actID).then((d: any) => {
      console.log(d)
      this.spinner.hide();
      this.showTable = true;
      return d;
    })

编辑:感谢您回答我的问题,我尝试了所有方法,前提是所有方法都有效,但我在调用时遇到问题 this.data 在每个。是异步的问题吗?

this.data.forEach(element => {
      element['properties'] = element.properties.map;
      columns.forEach(column => {
        if (column.header == 'PO Number') {
          if (column.hasMulValue) {
            column.value_list.forEach(value => {
              var column_value = this.adminService.loadColumnValue(value, element);
              if (column_value != null && column_value != '0') {

                element['po_num'] = column_value;

              }
            })
          }
        }
      })
      // element1.po_num = element1.properties.map.aclrq_poNum
      var x = new Date(element.properties.completionDate);
      var y = new Date("Oct 18, 2020");
      if ((element.taskType == "aclrq:PreparePo") && (x > y)) {
        arraynew.push(element)
      }
    })
vendor.js:69393 ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'forEach' of undefined
TypeError: Cannot read property 'forEach' of undefined
    

【问题讨论】:

  • 你在哪里调用 forEach
  • 在一个不同的函数中,我在一个函数中加载了两个 api,在同一个函数中,我正在调用另一个具有 forEach 的函数
  • 等待响应的函数是异步的,因此也会返回一个 Promise。您需要在调用第二个函数(使用 forEach)之前等待第一个函数(使用 async-await)的 Promise,或者在第一个函数的 then 回调中调用第二个函数
  • 如果我把所有的东西都放在一个异步函数中,面临异步问题。在这样做之前,我的情况一切正常。我只是想同时调用两个 api。

标签: angular typescript


【解决方案1】:

您可以使用Promise.all()

[this.data, this.APIresponse] = await Promise.all([
  this.processService.workflowAPI1(/**/),
  this.processService.workflowAPI(/**/)
]);

【讨论】:

  • 我已经尝试过你的方法,但我遇到了异步问题,如何解决这个问题?
【解决方案2】:

我假设您正在使用 Angular HttpClient 进行 HTTP 调用并将它们返回的 observables 转换为服务中的 promise。

如果是这种情况,请避免将它们转换为 Promise 并直接使用 observables。然后,您可以使用 RxJS forkJoin 函数并行触发多个请求。此外,还可以使用 RxJS 运算符,如 tapfinally 来验证响应并隐藏微调器。

试试下面的

import { forkJoin } from 'rxjs';
import { tap, finally } from 'rxjs/operators';

forkJoin({
  data: this.processService.workflowAPI1('activiti$requisitionandpo', 'COMPLETED'),
  APIresponse: this.processService.workflowAPI(selected_actID).pipe(
    tap(d => console.log(d)),    // <-- `tap` to confirm if the response is emitted
    finally(() => {              // <-- `finally` to hide spinner and show table when the request completes
      this.spinner.hide();
      this.showTable = true;
    })
  )
}).subscribe({
  next: response => {
    this.data = respose.data;
    this.APIresponse = response.APIresponse;
  },
  error: error => {
    // handle error
  }
});

如果出于任何原因您必须使用 promise 来获取数据,您可以使用 RxJS from 函数将它们转换为 observables,然后如上所示继续

import { from, forkJoin } from 'rxjs';
import { tap, finally } from 'rxjs/operators';

forkJoin({
  data: from(this.processService.workflowAPI1('activiti$requisitionandpo', 'COMPLETED')),    // <-- convert promise to observable
  APIresponse: from(this.processService.workflowAPI(selected_actID)).pipe(                   // <-- convert promise to observable
    ...
  )
}).subscribe(...);

更新:this.data 未定义

变量this.data 是异步分配的。所以任何直接依赖它的语句都必须在订阅中。

import { forkJoin } from 'rxjs';
import { tap, finally } from 'rxjs/operators';

forkJoin({
  ...
}).subscribe({
  next: response => {
    this.APIresponse = response.APIresponse;
    this.data = response.data;
    this.data.forEach(element => {  // <-- this should be inside the subscription
      ...
    });
  },
  error: error => {
    // handle error
  }
});

您可以了解有关异步数据的更多信息here

【讨论】:

  • 我需要在外面打电话给this.data。我正在尝试在其他功能中使用它,因此我将其声明为属性
  • 简短回答:你不能。请参考链接的答案以了解您为什么不能这样做。您需要将输出缓存到服务中的 observable 并在组件中使用它,或者直接订阅需要输出的源。
【解决方案3】:

这里 rxjs 运算符 forkJoin 会来为您提供帮助。但首先,您必须将您的承诺转换为可观察的,以便使用 from rxjs 运算符。所以首先导入需要的操作符

import {from, forkJoin} from 'rxjs';

然后像这样使用 forkJoin 运算符

let req1$ = from(this.processService.workflowAPI1('activiti$requisitionandpo', 'COMPLETED'));
let req2$ = from(this.processService.workflowAPI(selected_actID));
//pass both api calls to the forkJoin operator
forkJoin(req1$, req2$).subscribe(([res1, res2])=>{

//response of first api call
console.log(res1);

//response of second api call
console.log(res2);
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-08
    • 2017-12-24
    • 2021-11-01
    • 1970-01-01
    • 2022-01-14
    • 2021-02-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多