3

I am using async each to loop through and constructing an object called coupon_bo. Surprisingly inside processbo function, I am seeing a side effect where only the last copy of coupon_bo object is available to processbo function.

My understanding is that since coupon_bo is local to each iteration, there should be a new object for iteration.

Am I missing something?

function hitApplyLogic(coupon_names, coupons_list, req, callback) {
    async.each(coupon_names, function(coupon_name, callback) {
        var coupon_bo = new coupon_objects.CouponsBO();
        coupon_bo.incoming_request = req.body;
        coupon_bo.incoming_request['coupon_code'] = coupon_name.cn;
        coupon_bo.incoming_request['list_offers'] = true;

        setTimeout(function()
        {
            console.log("CONSOLE-BO: " + JSON.stringify(coupon_bo));

        }, 1000);
    });
}
9
  • please put some more code, like where are you calling callback and all Commented Oct 1, 2016 at 17:17
  • async.each() run asynchronously and may corrupt your data coupon_bo. You may like to use async.eachSeries() or use this.coupon_bo rather than var coupon_bo Commented Oct 1, 2016 at 17:17
  • @suraj99934 callback is called inside the function(result) {} Commented Oct 1, 2016 at 17:27
  • can you replace this async.each(coupon_names, function(coupon_name, callback) { with async.eachLimit(coupon_names, 1, function(coupon_name, callback) { and check problem is still occuring? Commented Oct 1, 2016 at 17:30
  • @suraj99934 see the updated code. It reproduces the problem which is happening. Always last BO is printed in console.log. I guess that's behaviour of each, it doesn't create a new scope Commented Oct 1, 2016 at 17:35

2 Answers 2

1

async.each has no guarantee of running the tasks in order.

Per the documentation:

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

I'm not sure what you meant by processbo function. But var coupon_bo should be unique to each instance of the iteratee that is ran. So there should be no issue of it being overwritten by the other ones.

I'm also not sure why you're using setTimeout to log coupon_bo after 1s.

I did find something missing in your implementation which is the call to the callback function in the iteratee async.each(coupon_names, function(coupon_name, callback) {

Without calling it you'll be forever stuck at async.each

function hitApplyLogic(coupon_names, coupons_list, req, callback) {
    async.each(coupon_names, function(coupon_name, eachCallback) { //Changed callback to eachCallback to avoid confusion with the one received in hitApplyLogic
        var coupon_bo = new coupon_objects.CouponsBO();
        coupon_bo.incoming_request = req.body;
        coupon_bo.incoming_request['coupon_code'] = coupon_name.cn;
        coupon_bo.incoming_request['list_offers'] = true;

        setTimeout(function()
        {
            console.log("CONSOLE-BO: " + JSON.stringify(coupon_bo));
            eachCallback(null); // Finished doing all the work with this particular coupon_name
        }, 1000);
    },
    , function(err) { //This function is called once all the coupon_names were processed

        if(err) {
          // One of the coupon_names returned an error
          console.log('One of the coupon_names returned an error');
          return callback(err); // Callback received in hitApplyLogic
        } else {
          // Everything went OK!
          console.log('All coupons were constructed');
          return callback(null); // Callback received in hitApplyLogic
        });
}
Sign up to request clarification or add additional context in comments.

Comments

0

Here is the Solution for your problem, Async's each immediately prints out all elements

async.eachSeries() will iterate array item one at a time, where async.each() will iterate all the items at once in parallel.

2 Comments

I need the parallelism
If you want parallel operation without error iterating, I suggest you to use async.waterfall (caolan.github.io/async/docs.html#.waterfall) inside async.each to call your function on every iteratiion.

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.