Promise.all 奇怪的分辨率问题

Promise.all strange resolution issue

调用时考虑这两个函数 getStatusAll(数据)-

data=[[],['1'],['2'],['3']];

async function getStatusAll(data) {
    console.log("In getStatusAll");
  try{
    let statusPromiseArray =  data.map(async(value) => { 
      result= await this.fetchStatusDBs(value);
      return result;
    });
    statusResolvedArray= await Promise.all(statusPromiseArray)
    return statusResolvedArray;
  }catch(err){
    throw(err);
  }
}

async function fetchStatusDBs(data) {
    console.log("In fetchStatusDBs");
  try{
      //fetch status in dvf_req_id for an dvf_req_id
      if(data.length==0){
        console.log("1");
        dvfStatus = await Promise.resolve("Disabled");
        console.log("2");
        trainingStatus = await Promise.resolve("Disabled");
        console.log("3");
        inferenceStatus = await Promise.resolve("Disabled");
      }
      else {
        console.log("4");
        dvfStatus = await Promise.resolve("Enabled");
        console.log("5");
        trainingStatus = await Promise.resolve("Enabled");
        console.log("6");
        inferenceStatus = await Promise.resolve("Enabled");
      }
      return [dvfStatus,trainingStatus,inferenceStatus];
  }catch(err){
    throw(err);
  }
}

我正在尝试解决 Promise.all 中的多个 Promise 但结果出人意料。 实际输出-

In getStatusAll
In fetchStatusDBs
1
In fetchStatusDBs
4
In fetchStatusDBs
4
In fetchStatusDBs
4
2
5
5
5
3
6
6
6
[["Enabled","Enabled","Disabled"],["Enabled","Enabled","Enabled"],["Enabled","Enabled","Enabled"],["Enabled","Enabled","Enabled"]]

预期输出-

In getStatusAll
inside map
In fetchStatusDBs
1
2
3
inside map
In fetchStatusDBs
4
5
6
inside map
In fetchStatusDBs
4
5
6
inside map
In fetchStatusDBs
4
5
6
[["Disabled","Disabled","Disabled"],["Enabled","Enabled","Enabled"],["Enabled","Enabled","Enabled"],["Enabled","Enabled","Enabled"]]



但是像这样更改 fetchStatusDBs returns 以正确的格式输出。

async function fetchStatusDBs(data) {
    console.log("In fetchStatusDBs");
  try{
      if(data.length==0){
        dvfStatus = "Disabled";
        trainingStatus = "Disabled";
        inferenceStatus = "Disabled";
      }
      else {
        dvfStatus = "Enabled";
        trainingStatus = "Enabled";
        inferenceStatus = "Enabled";
      }
      return [dvfStatus,trainingStatus,inferenceStatus];
  }catch(err){
    throw(err);
  }
}

有人可以帮我吗?

您的主要问题是 fetchStatusDBs 中的状态变量未声明,因此 implicitly global。由于您的代码正在进行多个并发调用,这些调用在 await 暂停点处交错,因此它们相互影响 - 一个典型的竞争条件。要解决此问题,只需使用 letvar.

声明变量
const data=[[],['1'],['2'],['3']];

async function getStatusAll(data) {
    console.log("In getStatusAll");
    let statusPromiseArray = data.map(this.fetchStatusDBs, this);
    return Promise.all(statusPromiseArray);
}

async function fetchStatusDBs(data) {
    console.log("In fetchStatusDBs");
    let dvfStatus, trainingStatus, inferenceStatus;
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    //fetch status in dvf_req_id for an dvf_req_id
    if (data.length==0) {
        console.log("1");
        dvfStatus = await Promise.resolve("Disabled");
        console.log("2");
        trainingStatus = await Promise.resolve("Disabled");
        console.log("3");
        inferenceStatus = await Promise.resolve("Disabled");
    } else {
        console.log("4");
        dvfStatus = await Promise.resolve("Enabled");
        console.log("5");
        trainingStatus = await Promise.resolve("Enabled");
        console.log("6");
        inferenceStatus = await Promise.resolve("Enabled");
    }
    return [dvfStatus, trainingStatus, inferenceStatus];
}

这将得到预期的结果(return 值)。为了从日志中获得预期的输出,您不能将 map 与异步函数一起使用,然后使用 Promise.all 等待所有承诺,但您需要按顺序进行调用:

async function getStatusAll(data) {
    console.log("In getStatusAll");
    const statusArray = [];
    for (const value of data) {
//  ^^^^^^^^^^^^^^^^^^^^^^^^^
        statusArray.push(await this.fetchStatusDBs(value));
//                       ^^^^^
    }
    return statusArray ;
}

你对async-await有几个误解

async function getStatusAll(data) {
    console.log("In getStatusAll");
  <del>try{</del>
    let statusPromiseArray =  data.map(async(value) => { // map is sync
      result= await this.fetchStatusDBs(value); // global result
      return result; // return-await anti-pattern
    });
    statusResolvedArray= await Promise.all(statusPromiseArray) // global
    return statusResolvedArray; // return-await anti-pattern
  <del>}catch(err){</del>  // catch-throw anti-pattern
    <del>throw(err);</del>
  <del>}</del>
}

所有这些都可以写成-

function getStatusAll(data) {
  return Promise.all(data.map(v => this.fetchStatusDBs(v)))
}

任何错误都会自动冒出来。无需catch和重新throw。这将在 并行 中执行所有提取。如果需要,您可以在 serial 中执行请求。这表明在 async -

中正确使用 await
async function getStatusAll(data) {
  const result = []
  for (const value of data)
    result.push(await this.fetchStatusDBs(value))
  return result
}