Search code examples
javascriptnode.jsasynchronousforeachnode-async

Trying to use async.forEach Serially but Fails - Node.js


forEach , i am using the async library . in the foreach loop i will call a different service and get data . those data should be in order to process it in my view , because these are some dress details and need to be in order . so i tried to make the foreach loop synchronous by adding the done() inside the external service callback.

var address_deails = [];
var x = 0;

async.forEach(lat_long, function (item, done) {
    external_servie(item,config,function (err, data) {
        if (err) {
            callback(err, null);
        } else {
            //code here .......
            address_deails[x]  = //some_data;
        }
        x++;
        done();  <------------- Here 
    });
}, function(err) {
    if(err) {
        callback(err,null)
    } else {
        callback(err,address_deails)
    }
});

but i am getting values in a different order each time .

I want to get array keys in order like 0,1,2 .

As per my knowledge i thought if you use done() inside the callback , until the callback returns , the forEach loop will wait .

Does the async.forEach work differently ?

Can you give me any suggestion so that i can solve my issue , may using an other library than async .

Thanks in advance .


Solution

  • async.forEach() is an alias for async.each and the doc says:

    Note, that since this function applies iteratee to each item in parallel, there is no guarantee that the iteratee functions will complete in order.

    What you're looking for is async.eachSeries()/async.forEachSeries():

    async.eachSeries(lat_long, function (item, done) {
        external_servie(item,config,function (err, data) {
            if (err) {
                callback(err, null);
            } else {
                //code here .......
                address_deails[x]  = //some_data;
            }
            x++;
            done();  <------------- Here 
        });
    }, function(err) {
        if(err) {
            callback(err,null)
        } else {
            callback(err,address_deails)
        }
    });
    

    And now you can push into address_deails instead of maintaining an index: address_deails.push(/* some data */);.

    There is also an issue on your external_service's error management:

    external_servie(item,config,function (err, data) {
        if (err) {
            done(err); // <<< call done with the error to stop the loop or it will continue
        } else {
            //code here .......
            address_deails.push(/* some data */);        
        }
        done();  <------------- Here 
    });