Как реализовать асинхронный цикл? - PullRequest
0 голосов
/ 11 апреля 2019

У меня есть коллекция под названием '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 ]

1 голос
/ 11 апреля 2019

Если вы хотите дождаться getResult, вам нужно вернуть Promise из result.map callback.

Вы ничего не подталкиваете к 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 loop

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);
});
0 голосов
/ 11 апреля 2019

Это должно работать, если все лексические рамки приняты к рассмотрению. Асинхронизация каждого также является лучшим вариантом, он уменьшит, если еще блокирует и управляет обещанием для вас.

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);
        }
    });
0 голосов
/ 11 апреля 2019

Массив для метода forEach не будет работать с асинхронной функцией (если вы не совершите глубоко злых дел, таких как переопределение прототипа). Этот вопрос имеет хорошее представление о внутреннем.

Если вы не хотите полагаться на внешние библиотеки, простой (и мой любимый) подход выглядит примерно так:

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

Просто адаптируйте его под свои нужды! :)

0 голосов
/ 11 апреля 2019

Возможно, вы захотите использовать цикл for await of.Подробнее см. в этом блоге .

Это, IMHO, самый современный способ сделать это, и он не требует загрузки каких-либо внешних зависимостей, так как он встроен.в самом языке.Это в основном очень похоже на классический for of цикл.

0 голосов
/ 11 апреля 2019

используйте 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
});
...