1

I want to add have nested DB query inside a eachOf loop which should be synchronous. Tried so many combinations and which but nothing works for inside of foreach loop.

   async.eachOf(nc.virtual_devices, function (vd) {
         ///////// This code work fine /////////////
        var domain = extractDomain(vd.api_url);
        vd.raw_api_ip = vd.api_ip;
        vd.api_ip = getProxiedPath(vd.api_ip);
        vd.raw_api_url = vd.api_url;
        vd.api_url = nconf.get('PROXIED_PATH_SCHEME') + vd.api_ip + vd.api_url.split(domain)[1];
          // Path to websocket notifications
        vd.ws_url = nconf.get('PROXIED_PATH_SCHEME') + vd.api_ip + vd.notification_base_uri;

     //// THIS CODE IS NOT FINE //////////////
        if (nc.type === 'XXX'){

            var promise = new Promise (function (resolve,reject) {

            console.log("********XX VD TYPE **********");
            console.log(JSON.stringify(vd));
            console.log("VD ID VALUE IS ", vd.id);
            var newID = (vd.id).replace(/\d_/, "");
            console.log("VD ID VALUE IS ", newID);

            var _idofSubgroup;
            var labeltoSearch = nc.type + ' ' + nc.version;
            pattern = "/^" + newID + "/i";
            test = _idofSubgroup;
            pattern = newID;
            console.log(pattern);

            db.collection('subgroups').findOne({label: labeltoSearch}, function (err, result) {
                console.log(result._id);
                _idofSubgroup = result._id;

                db.collection('exploreposts').find({subgroup: result.id_}, {title: {"$regex": pattern}}).toArray(function (err, results) {
                    console.log(results);
                })
        });
        })
    }
  });

Tried with promise inside it but that also in pain. This is my tried code which is not working fine. Any suggestion would be appreciated., as simply said i have been stuck in callback hell

   async.eachOf(nc.virtual_devices, function (vd) {
         ///////// This code work fine /////////////
        var domain = extractDomain(vd.api_url);
        vd.raw_api_ip = vd.api_ip;
        vd.api_ip = getProxiedPath(vd.api_ip);
        vd.raw_api_url = vd.api_url;
        vd.api_url = nconf.get('PROXIED_PATH_SCHEME') + vd.api_ip + vd.api_url.split(domain)[1];
          // Path to websocket notifications
        vd.ws_url = nconf.get('PROXIED_PATH_SCHEME') + vd.api_ip + vd.notification_base_uri;

     //// THIS CODE IS NOT FINE with promises also  //////////////
        if (nc.type === 'XXX'){

            var promise = new Promise (function (resolve,reject) {

            console.log("********XX VD TYPE **********");
            console.log(JSON.stringify(vd));
            console.log("VD ID VALUE IS ", vd.id);
            var newID = (vd.id).replace(/\d_/, "");
            console.log("VD ID VALUE IS ", newID);

            var _idofSubgroup;
            var labeltoSearch = nc.type + ' ' + nc.version;
            pattern = "/^" + newID + "/i";
            test = _idofSubgroup;
            pattern = newID;
            console.log(pattern);

            db.collection('subgroups').findOne({label: labeltoSearch}, function (err, result) {
                console.log(result._id);
                _idofSubgroup = result._id;
                resolve ({id_:_idofSubgroup,pattern1 : pattern});
            })
        });
        promise.then (function(result) {
            console.log(result.id_);
            console.log(result.pattern1);
                db.collection('exploreposts').find({subgroup: result.id_}, {title: {"$regex": result.pattern1}}).toArray(function (err, results) {
                    console.log(results);
                })
        },function (err){
            console.log (err);
       })


    }
  });
Inder R Singh
  • 652
  • 1
  • 6
  • 21
  • Focus on the `iteratee` description of the [async#eachOf](http://caolan.github.io/async/docs.html#eachOf) section. When you work with async.js loop statements, you usually need/want to call the passed `callback` when an error occurs or once you are done with the task. – Mikey Aug 22 '17 at 18:44
  • But how does it link with Mongodb query which is inside that loop , i honestly dontunderstand it. – Inder R Singh Aug 22 '17 at 19:08

1 Answers1

1

It doesn't seem you need to use async.eachOf, but async.each() or async.eachSeries().

This is untested but it would look something like

async.eachSeries(nc.virtual_devices, function iteratee(vd, cb) {
    console.log('calling iteratee()')
    
    var domain = extractDomain(vd.api_url);
    vd.raw_api_ip = vd.api_ip;
    vd.api_ip = getProxiedPath(vd.api_ip);
    vd.raw_api_url = vd.api_url;
    vd.api_url = nconf.get('PROXIED_PATH_SCHEME') + vd.api_ip + vd.api_url.split(domain)[1];
     // Path to websocket notifications
    vd.ws_url = nconf.get('PROXIED_PATH_SCHEME') + vd.api_ip + vd.notification_base_uri;

    // skip the rest if type is XXX;
    // you need to explicitedly call the original callback i.e. cb
    // note the use of return to prevent execution of the rest of the code
    if (nc.type !== 'XXX')
        return cb(null); // or cb();

    console.log("********XX VD TYPE **********");
    console.log(JSON.stringify(vd));
    console.log("VD ID VALUE IS ", vd.id);
    var newID = (vd.id).replace(/\d_/, "");
    console.log("VD ID VALUE IS ", newID);

    // I have no idea what is going here
    var _idofSubgroup;
    var labeltoSearch = nc.type + ' ' + nc.version;
    var pattern = "/^" + newID + "/i";
    test = _idofSubgroup;
    pattern = newID;
    console.log(pattern);
    
    // we're going to use waterfall here as you have 2 async operations, where one is dependent on the other 
    async.waterfall([
        function getSubgroup(cb1) {
            console.log('calling getSubgroup')
            db.collection('subgroups').findOne({ label: labeltoSearch }, function (err, subgroup) {
                // if an error occurs, stop waterfall-loop
                // you do this by passing the error in the callback
                // again note the use of return here to prevent execution of the rest of the code
                if (err) return cb1(err);
                // pass the data to the next task
                cb1(null, subgroup, pattern);
            });
        },
        function getPosts(subgroup, pattern, cb2) {
            // we will only get here if the last task ^ went through
            console.log('calling getPosts')
            db.collection('exploreposts').find({ subgroup: subgroup._id, title: { $regex: pattern }}).toArray(function (err, posts) {
                // if an error occurs, stop waterfall-loop
                if (err) return cb2(err);
                // do something with posts
                console.log('posts', posts);
                // otherwise, keep going
                // since there are no more waterfall-tasks, waterfall ends
                cb2();
            });
        }
    ], function (err) {
        console.log('waterfall() done');
        // if an error occurred during the waterfall-loop, it will come down here
        // we will let the original callback i.e. cb deal with this error though
        if (err) return cb(err);
        // otherwise we're done
        // we will let the original callback know everything went well by calling it without any error
        cb();
    });
    
    // you could have also simply do
 // ], cb);
    

}, function (err) {
    console.log('eachSeries() done');
    // handle any error that came
    console.log(err);
    // send response
});

I purposely name the variables and functions so that you get an idea.

Follow the logs if there are any issues.

madth3
  • 7,275
  • 12
  • 50
  • 74
Mikey
  • 6,728
  • 4
  • 22
  • 45
  • Thank you .. it worked for me very well. Also any recommendations of tutorial to understand ambiguity of async programming in nodejs – Inder R Singh Aug 23 '17 at 13:46