-1

I have a collection called 'alldetails' which have the details of some collection

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

I have collection1,collection2 and collection3 which have column1,column2,colum3 respectively

I have to fetch all the name from the 'alldetails' and I have to get the min and max value of other table based on the column name.

So I want the output like below

{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"}]

}

I tried the below code because of non blocking its not waiting the response.

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);

});

Please suggest me a solution.

user1187
  • 2,116
  • 8
  • 41
  • 74

5 Answers5

1

If you want to wait for getResult then you need to return Promise from result.map callback.

You are not pushing anything to resolvedFinalArray so why bother with 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);
});

or using 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);
});
ponury-kostek
  • 7,824
  • 4
  • 23
  • 31
0

use async.eachOfLimit if you want to apply an async function on all element of an array:

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
});
Daphoque
  • 4,421
  • 1
  • 20
  • 31
0

The array forEach method won't work with async function (unless you do deeply evil things like redefining the prototype). This question has a nice insight of the internal.

If you don't want to rely on external libraries, an easy (and my favourite) approach is something like:

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

Just adapt it to your need! :)

pierpytom
  • 1,202
  • 1
  • 12
  • 25
0

You might want to use the for await of loop. See this blog post for details.

This, IMHO, is the most modern way to do it, and it doesn't require you to load any external dependencies, since it is built-in to the language itself. It's basically very similar to the classical for of loop.

Golo Roden
  • 140,679
  • 96
  • 298
  • 425
0

This should work, if all lexical scope are taken to consideration. Async each is also is better option it would reduce if else blocks and manage promise for you.

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);
        }
    });
Bharath
  • 390
  • 1
  • 6