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


    }
  });
2
  • Focus on the iteratee description of the async#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. Commented Aug 22, 2017 at 18:44
  • But how does it link with Mongodb query which is inside that loop , i honestly dontunderstand it. Commented Aug 22, 2017 at 19:08

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you .. it worked for me very well. Also any recommendations of tutorial to understand ambiguity of async programming in nodejs

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.