首页 > 解决方案 > 如何在nodeJS中的forEach中正确使用异步

问题描述

我正在使用这个 forEach 循环将一些数据推送到数组中并将其发送到客户端

   var arrayToSend = []  //Empty Array

   SomeArray.forEach(function(item){
        Collection.findById(item.id,function (err,data) {
          if (err) {
            console.log(err)
          } else {

            arrayToSend.push(data.record)
          }
  //How can I run this next line at end of loop  asynchronously
         res.render("index",{arrayToSend : arrayToSend })
        })
      })


    }

如何在 forEach 范围内以回调的形式循环结束后使用 async 运行res.render("index",{arrayToSend : arrayToSend }),否则如果我在循环外运行它,它将发送空数组?

标签: javascriptnode.jsexpressasynchronousasync-await

解决方案


而不是.forEach,用于.map将每个项目映射someArray到一个 Promise,以便您可以创建一个 Promise 数组。如果你调用Promise.all那个数组,你会得到一个 Promise,它会在数组中的所有 Promise 都解决后解决。

因为findById是基于回调的,而不是基于Promise的,所以需要先将每个回调转化为一个Promise:

const promises = someArray.map((item) => new Promise((resolve, reject) => {
  Collection.findById(item.id, (err,data) => {
    if (err) return reject(err);
    resolve(data.record);
  });
}));
Promise.all(promises)
  .then(arrayToSend => {
    res.render("index", { arrayToSend });
  })
  .catch((err) => {
    // handle errors
  });

如果你想容忍错误findById并且仍然构建一个arrayToSend没有错误的项目,你可以push到一个外部数组(类似于你最初所做的)并且resolve无条件地,无论是否findById导致错误:

const arrayToSend = [];
const promises = someArray.map((item) => new Promise((resolve, reject) => {
  Collection.findById(item.id, (err,data) => {
    if (err) console.log(err);
    else arrayToSend.push(data.record);
    resolve();
  });
}));
Promise.all(promises)
  .then(() => {
    res.render("index", { arrayToSend });
  })

推荐阅读