【问题标题】:How to implement async in for loop?如何在for循环中实现异步?
【发布时间】:2019-04-11 19:28:40
【问题描述】:

我有一个名为“alldetails”的集合,其中包含一些集合的详细信息

{
    "name" : "Test1",
    "table_name" : "collection1",
    "column_name" : "column1"
},
{
    "name" : "Test2",
    "table_name" : "collection2",
    "column_name" : "column2"
},
{
    "name" : "Test3",
    "table_name" : "collection3",
    "column_name" : "column3"
}

我有collection1、collection2和collection3,它们分别有column1、column2、colum3

我必须从“alldetails”中获取所有名称,并且必须根据列名获取其他表的最小值和最大值。

所以我想要下面的输出

{name: ["Test1","Test2","Test3"],
date: [{min_date: "2018-12-01", max_date: "2018-12-31", name: "Test1"},
              {min_date: "2018-12-01", max_date: "2018-12-31", name: "Test2"},
              {min_date: "2018-12-01", max_date: "2018-12-31", name: "Test3"}]

}

我尝试了下面的代码,因为它没有等待响应。

alldetails.find({}, { _id: 0 }).then(async function(result) { 
    let result_data = {};  
    let resolvedFinalArray = {};
    let array = [];
    result_data["name"]= [];
    result_data["date"] = [];
    resolvedFinalArray = await Promise.all(result.map(async value => { 
      result_data["name"].push(value.name)  
      getResult(value.table_name,value.column_name,function(response){
           result_data["date"].push({min_date: response.minvalue, max_date: response.maxvalue, name:value.name})          
       });     
    }));
    setTimeout(function()
    { 
      console.log(resolvedFinalArray);
    }, 3000);

});

请给我一个解决方案。

【问题讨论】:

标签: node.js promise async-await


【解决方案1】:

如果你想等待getResult,那么你需要从result.map回调中返回Promise

您没有向resolvedFinalArray 推送任何内容,所以为什么要打扰console.log(resolvedFinalArray)

alldetails.find({}, {_id: 0}).then(async (result) => {
    let result_data = {};
    result_data["name"] = [];
    result_data["date"] = [];
    await Promise.all(result.map(value => {
        // create Promise that resolves where getResult callback is fired
        return new Promise((resolve) => {
            getResult(value.table_name, value.column_name, (response) => {
                result_data["name"].push(value.name);
                result_data["date"].push({
                    min_date: response.minvalue,
                    max_date: response.maxvalue,
                    name: value.name
                });
                resolve();
            });
        });
    }));
    console.log(result_data);
});

或使用for循环

alldetails.find({}, {_id: 0}).then(async (result) => {
    let result_data = {};
    result_data["name"] = [];
    result_data["date"] = [];
    for (let i = 0; i < result.length; i++) {
        const value = result[i];
        await new Promise((resolve) => {
            getResult(value.table_name, value.column_name, (response) => {
                result_data["name"].push(value.name);
                result_data["date"].push({
                    min_date: response.minvalue,
                    max_date: response.maxvalue,
                    name: value.name
                });
                resolve();
            });
        });
    }
    console.log(result_data);
});

【讨论】:

    【解决方案2】:

    如果要对数组的所有元素应用异步函数,请使用 async.eachOfLimit:

    var async = require("async");
    var array = [{_id: "...."},{...},{...}];
    
    async.eachOfLimit(array, 1, function(element, index, cb){
    
    
        myAsyncFunctionWithMyElement(element, function(err){
            return cb(err);
        });
    
    }, function(err){
      // final callback
    });
    

    【讨论】:

      【解决方案3】:

      数组 forEach 方法won't work with async function(除非你做了一些非常邪恶的事情,比如重新定义原型)。 This question 对内部有很好的洞察力。

      如果您不想依赖外部库,一种简单的(也是我最喜欢的)方法如下:

          for (let i = 0; i < <your array>.length; i++ ) {
              await Promise.all( <your logic> );
          }
      
      

      只需根据您的需要进行调整! :)

      【讨论】:

        【解决方案4】:

        您可能想要使用for await of 循环。详情请见this blog post

        恕我直言,这是最现代的方法,它不需要您加载任何外部依赖项,因为它是语言本身内置的。它基本上与经典的for of 循环非常相似。

        【讨论】:

          【解决方案5】:

          如果考虑到所有词法范围,这应该可以工作。 Async each 也是更好的选择,它会减少 if else 阻止并为您管理承诺。

          alldetails.find({}, { _id: 0 })
              .exec((err, result) => {
                  if (!err) {
                      let resolvedFinalArray = [];
                      result.map((value) => {
                          resolvedFinalArray.push({
                              name: value.name,
                              date: []
                          });
                          getResult(value.table_name, value.column_name, (err, response) => {
                              if (!err) {
                                  resolvedFinalArray[resolvedFinalArray.indexOf(value.name)]['date'].push({
                                      min_date: response.minvalue, 
                                      max_date: response.maxvalue, 
                                      name:value.name
                                  });
                              } else {
                                  // Send your error messsage.
                                  // res.status(500).send(err);            
                              }
                          });
                      });
                      console.log(resolvedFinalArray);
                      // res.send(resolvedFinalArray);
                  } else {
                      // Send your error messsage.
                      // res.status(500).send(err);
                  }
              });
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-02-15
            • 2021-10-28
            • 2017-05-19
            • 2016-09-17
            • 2018-03-14
            • 1970-01-01
            • 2012-04-16
            • 2021-09-26
            相关资源
            最近更新 更多