2

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.

4

2 回答 2

4

这不是异步问题,而是闭包问题。

尝试这个:

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

或这个:

people.forEach (function (p){
  tasks.push( function(callback) {
    setTimeout( makePrintFunction(p, callback), 200); 
  });
});
于 2013-04-30T15:30:45.690 回答
3

您正在处理经典范围问题。尝试这个:

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

甚至更好

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

或最好的:

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

发生这种情况是因为for循环没有创建范围,即触发函数时i是最后一个索引。现在函数确实创建了作用域,所以匿名函数内部i是期望值。

于 2013-04-30T15:28:39.003 回答