【问题标题】:await with Promise.all is not in effect等待 Promise.all 无效
【发布时间】:2018-10-27 16:38:24
【问题描述】:

下面是我的 async 函数,用于从数据库读取值并在控制台上记录一些内容。但由于某种原因,它没有发生。

所以,我创建了一组承诺,然后继续等待所有承诺解决,因为承诺将从数据库中读取。但是 Promise.all 上的 await 并没有暂停代码的执行,也没有等待所有承诺解决,而是将控制权传递回调用函数。 我在这里有什么遗漏吗?

async function readValuesFromDB(codes) {
  console.log('trying to read values from DB');
  let dbPromises = [];
  for(let code in codes) {
    let refId = 'some_random_reference_id_generated_from_codes[i]';
    dbPromises.push(MyDb.getPromise(refId)); // getPromise() returns a promise that reads from DB
  }
  console.log('waiting for all promises to resolve...');

  // waiting for all promises to finish 
  await Promise.all(dbPromises).then((allPromises) => {
    for(let i in allPromises) {
      console.log('OK..read from DB');
    }
  });
  console.log('all promises resolved');

}

console.log('calling readValuesFromDB()');
readValuesFromDB();
console.log('finished readValuesFromDB()');

上述调用的输出是:

trying to read values from DB
waiting for all promises to resolve...
finished readValuesFromDB
......
......
OK..read from DB
OK..read from DB
OK..read from DB
...
...
all promises resolved

理想的输出应该在下面(因为我正在等待使用 awaitPromise.all 解决所有承诺)

trying to read values from DB
waiting for all promises to resolve...
OK..read from DB
OK..read from DB
OK..read from DB
...
...

因此,在控件传递回调用函数后,promise 似乎正在得到解决,并且似乎 await 在这里没有任何效果。

关于为什么 await 在这种情况下无效的任何帮助?

【问题讨论】:

  • 调用readValuesFromDB() 时,您没有使用await,因此它不会等待函数在那里完成。 PS:我不会混合使用async/awaitPromise.then() 语法。
  • @Sirko 表示调用readValuesFromDB()的函数应该是async too ?
  • 或者使用readValuesFromDB().then( () => console.log('finished readValuesFromDB()') )
  • @Sirko。你对混合等待/然后是正确的。它的工作,但过于强调。我已经相应地编辑了我的答案
  • Don't use for…in enumerations on arrays! 还有,既然有await,为什么还要用then

标签: javascript node.js promise async-await es6-promise


【解决方案1】:

您在这里缺少等待:

(async function() {
  console.log('calling readValuesFromDB()');
  await readValuesFromDB();
  console.log('finished readValuesFromDB()');
})();

【讨论】:

  • 这是正确答案。 OP 代码存在很多 问题,但this answer 解释了为什么@ 987654322@ 在'all promises resolved' 之前记录。说到底,和Promise.all()一点关系都没有。
【解决方案2】:

行为正常。

readValuesFromDB 是异步运行的,而不是 console.log('finished readValuesFromDB()');

所以控制台在 readValuesFrom DB 解析之前解析“已完成”。

你可以这样做:

async function readValuesFromDB(codes) {
      console.log('trying to read values from DB');
      let dbPromises = [];
      for(let code in codes) {
        let refId = 'some_random_reference_id_generated_from_codes[i]';
        dbPromises.push(MyDb.getPromise(refId)); // getPromise() returns a promise that reads from DB
      }
      console.log('waiting for all promises to resolve...');
    
      // waiting for all promises to finish 
      let allPromises = await Promise.all(dbPromises);
  for(let i in allPromises) {
    console.log('OK..read from DB');          
  }  
  console.log('all promises resolved');
      console.log('finished readValuesFromDB()');
    }
    
    console.log('calling readValuesFromDB()');
    readValuesFromDB();

或者像这样:

async function readValuesFromDB(codes) {
  console.log('trying to read values from DB');
  let dbPromises = [];
  for(let code in codes) {
    let refId = 'some_random_reference_id_generated_from_codes[i]';
    dbPromises.push(MyDb.getPromise(refId)); // getPromise() returns a promise that reads from DB
  }
  console.log('waiting for all promises to resolve...');
  
  // waiting for all promises to finish 
  let allPromises = await Promise.all(dbPromises);
  for(let i in allPromises) {
    console.log('OK..read from DB');          
  }  
  console.log('all promises resolved');
  allPromises = ['a', 'b', 'c']; // Dumb values for example
  return allPromises;
}

console.log('calling readValuesFromDB()');
readValuesFromDB().then(response => {
   console.log('finished readValuesFromDB()');
   console.log(response)
});

【讨论】:

  • 但是,如果我想获取所有承诺中正在解析的数据怎么办。在这种情况下,.then 上的 readValuesFromDB 会起作用。不过还没试过。
  • 你可以。你只需要返回你的 promise.all 响应。我已经为此编辑了第二个示例
  • 我尝试了你的建议,但我仍然得到相同的行为...await on Promise.all 不会导致等待所有承诺解决并且控制权返回给调用函数,因此在解决所有承诺后,我需要的结果在执行的更晚阶段可用。无法理解为什么在 Promise.all 上的 await 不起作用。
  • 这很奇怪。你在生产吗? Promise.all 在所有承诺解决或第一次承诺被拒绝后解决。也许你的情况?
【解决方案3】:

您必须通过await 呼叫readValuesFromDB

console.log('calling readValuesFromDB()');
await readValuesFromDB();
console.log('finished readValuesFromDB()');

【讨论】:

  • 也就是说调用readValuesFromDB()的函数也应该是async
  • 这行不通。 Await 只能在异步函数中使用:stackoverflow.com/questions/43832490/…
  • 是的,因此您的解决方案不会产生任何影响。我不能用await 代替readValuesFromDB
  • 那么你应该返回一个 Promise 并使用.then
猜你喜欢
  • 2020-04-28
  • 2020-11-01
  • 2021-03-21
  • 2020-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-02
  • 2020-06-23
相关资源
最近更新 更多