0

I have following code & output. I don't understand why the function is receiving incorrect argument. Please provide pointers.

var tempAccounts = [];
var i;
for (i = 0; i < accountIDs.length; i++) {
    var accountID = accountIDs[i];
    console.log("Log1:" + accountID);
    tempAccounts.push(function(callback){createTempAccount(accountID, callback)})
}

async.parallel(tempAccounts, function (error, results) {
    if (error) {
        sendError(error, "error creating temp acounts", res, logTag);
    } else {
        res.set('Content-Type','application/json');
        res.send(200, {});
    }
});


function createTempAccount(accountID, callback)
{
  console.log("Log2:" + accountID);
  ...
}

Output:

Log1: 1234
Log1: abcd

Log2: 1234
Log2: 1234

What could be the issue here?

GJain
  • 5,025
  • 6
  • 48
  • 82
  • 4
    The main issue is that this does not provide an [MCVE](https://stackoverflow.com/help/mcve), so I suggest you read that and understand it then update accordingly. You probably actually really mean either [JavaScript closure inside loops – simple practical example](https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) or you are expecting "series" when you actually said "parallel". But sorting out which of those you mean is what the MCVE is for. – Neil Lunn Nov 26 '18 at 04:31
  • @NeilLunn .. That is the correct answer. Now I am getting expected output. Thank you so much! – GJain Nov 26 '18 at 04:37
  • You should preferably use `let` instead of `var` when you're writing code in `NodeJS`. – Kaushik Nov 26 '18 at 04:50

1 Answers1

1

You don't need all the extra code to see the problem. It can be reduced to the following snippet. When you defined the function in the loop you capture the a shared variable in a closure. Then later when you call those functions, you get just the one value:

var tempAccounts = [];
let accountIDs = [200, 400]
var i
for ( i = 0; i < accountIDs.length; i++) {
    var accountID = accountIDs[i];
    console.log("Log1:" + accountID);
    tempAccounts.push(function(){return accountID})
}
// all the same value
console.log(tempAccounts.map(i => i()))

The easiest way to deal with this is using let to define a new variable in each iteration of the loop:

var tempAccounts = [];
let accountIDs = [200, 400]
for (let i = 0; i < accountIDs.length; i++) {
    let accountID = accountIDs[i];
    console.log("Log1:" + accountID);
    tempAccounts.push(function(){return accountID})
}

// now you get the unqie values:
console.log(tempAccounts.map(i => i()))
Mark
  • 90,562
  • 7
  • 108
  • 148
  • Looks like we have older node.js version. I get this error SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode – GJain Nov 26 '18 at 04:47
  • Oh, that's a bummer, @GJain. It makes things so much easier. Maybe it wouldn't be hard to `'use strict'` even if just for specific functions. – Mark Nov 26 '18 at 04:49