如何在for循环中实现异步?

时间:2019-04-11 10:21:39

标签: node.js promise async-await

我有一个名为“ 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);

});

请给我建议解决方案。

5 个答案:

答案 0 :(得分:1)

如果您想等待getResult,则需要从Promise回调中返回result.map

您没有将任何事情推向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);
});

答案 1 :(得分:0)

如果要在数组的所有元素上应用异步函数,请使用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
});

答案 2 :(得分:0)

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

如果您不想依赖外部库,那么一种简单的方法(也是我的最爱)是这样的:

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

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

答案 3 :(得分:0)

您可能想使用for await of循环。有关详细信息,请参见this blog post

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

答案 4 :(得分:0)

如果考虑所有词法范围,这应该可以工作。 Async each也是更好的选择,它将减少其他情况下的阻塞并为您管理承诺。

$this->add('/sample/team/{tab:[a-zA-Z0-9-_]+}/{matchType:[0-9]+}',array('action' => 'teamAction'))->setName('sample');