为什么javascript不等待和forEach并执行下一行

时间:2018-03-08 12:11:58

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

当我在nodejs中创建我的api并尝试将mongoose返回计数推送到新创建的数组时,它不等待forEach并执行json.res()并给出null响应。我用的时候 setTimeout()然后它会给出正确的结果。

let newcategories = [];
let service = 0;
const categories = await Category.find({}, '_id name');
categories.forEach(async (category) => {

service = await Service.count({category: category});

newcategories.push({ count:service });
console.log('newcategories is -- ', newcategories);

});  /* while executing this forEach it's not wait and execute res.json..*/


console.log('result --- ',result);
console.log('out newcategories is -- ', newcategories);
res.json({status: 200, data: newcategories});

2 个答案:

答案 0 :(得分:2)

您需要使用map而不是foreEach来收集等待并等待它们完成。编辑:或者您可以使用非常整洁的for..of(感谢其他人)!



const categories = ['a', 'b', 'c'];

function getNextCategory(oldCategory) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(String.fromCharCode(oldCategory.charCodeAt(0)+1));
    }, 1000);
  });
}

async function blah() {
  const categoryWaits = categories.map(async (category) => {
    return await getNextCategory(category);
  });

  const nextCategories = await Promise.all(categoryWaits);

  console.log(nextCategories);
}

blah();

async function blah2() {
  const nextCategories = [];

  for (category of categories) {
    nextCategories.push(await getNextCategory(category));
  };

  console.log(nextCategories);
}


blah2();




答案 1 :(得分:0)

所以你遇到的问题是async标记的函数将默认返回一个promise,但是Array.prototype.forEach方法并不关心你的回调函数的结果类型,它只是执行一个动作。

async功能中,它会正确地await您的回复并填写您的新类别,但类别上的forEach循环将会消失。

您可以选择将语句转换为for .. of循环,也可以使用map然后使用await Promise.all( mapped )

for..of循环就像这样

for (let category of categories) {
  service = await Service.count({category: category});

  newcategories.push({ count:service });
  console.log('newcategories is -- ', newcategories);
}

地图版本看起来像这样

await Promise.all( categories.map(async (category) => {
  service = await Service.count({category: category});

  newcategories.push({ count:service });
  console.log('newcategories is -- ', newcategories);
}));

第二个版本的确有效,因为Promise.all只有在所有承诺完成后才会解决,并且地图将为每个类别返回一个可能未解决的承诺