I am using Async's Library Parallel method wrong? But how?

I am using the async library's parallel function, but I am running into a weird problem. I loop through an array of objects to create an array of functions called people. People gets passed into async's parallel method to execute in parallel. However, when I take a look at the parameter "people" that actually get passed into the "printFunction" it is wrong. The people parameter is always the last object in my people array.

So in this example, the console log in printFunction would print

{ 'name' : 'jar jar binks' }
{ 'name' : 'jar jar binks' }

Code:

var people = [{ 'name' : 'obi wan kenobi'}, { 'name' : 'jar jar binks' }];

// Create an array of tasks to be processed.
for(var i = 0; i < people.length; i++) {
  tasks.push( function(callback) {
    setTimeout( makePrintFunction(people[i], callback), 200); 
  });
}

// Process those tasks.
async.parallel(tasks, function(err, stuff) {
  // ...do some stuff with the returned array here.
});

Make Print Function:

function makePrintFunction(people, next) {
  return validateAndTrackFlag(people, next);
}

function printFunction(people, next) {
  console.log(people);        // Always prints: { 'name' : 'jar jar binks' }
  next(null, true)
}

Obviously this is not the real code, I just changed the names and objects.

Thanks for any help in advance.

This is not an async problem, it's a closure problem.

Try this:

for(var i = 0; i < people.length; i++) {
  (function (i){
    tasks.push( function(callback) {
      setTimeout( makePrintFunction(people[i], callback), 200); 
    });
  })(i)
}

Or this:

people.forEach (function (p){
  tasks.push( function(callback) {
    setTimeout( makePrintFunction(p, callback), 200); 
  });
});

You are dealing with classical scoping issue. Try this:

for(var i = 0; i < people.length; i++) {
  (function(i) {
    tasks.push( function(callback) {
      setTimeout( makePrintFunction(people[i], callback), 200); 
    });
  })(i);
}

or even better

var create_scope = function(i) {
  tasks.push( function(callback) {
    setTimeout( makePrintFunction(people[i], callback), 200); 
  });
};
for (var i = 0; i < people.length; i++) {
  create_scope(i);
}

or the best:

people.forEach(function(person) {
  tasks.push( function(callback) {
    setTimeout( makePrintFunction(person, callback), 200); 
  });
});

This happens because for loop does not create a scope, i.e. when functions are fired i is the last index. Now functions do create scope, so inside anonymous function i is the expected value.