Shamoon
Shamoon

Reputation: 43531

What is the variable scope for async tasks?

var itemIds, result, taskQueue, _i, _len;
itemIds = [];
taskQueue = async.queue(function(task, callback) {
  console.log('Hello ' + task.name);
  return callback();
}, 10);
for (_i = 0, _len = results.length; _i < _len; _i++) {
  result = results[_i];
  taskQueue.push({}, function(err) {
    var item;
    item = new Item(result);
    return item.save(function(err, new_item) {
      itemIds[itemIds.length] = new_item._id;
      console.log(new_item._id);
      return console.log(itemIds);
    });
  });
}
taskQueue.drain = function() {
  console.log('Queue Done!');
  return console.log(itemIds.length);
};

is my code. But itemIds shows as empty when the drain is run. This is using the async module for node.js by the way

Upvotes: 0

Views: 950

Answers (2)

Raynos
Raynos

Reputation: 169411

I'd personally recommend you heavily simplify the code using after

var slice = Array.prototype.slice;

var cb = after(results.length, function() {
    var items = slice.call(arguments);
    console.log("All done");
    console.log(items.length);
});

results.forEach(function(result) {
    item = new Item(result);
    item.save(function(err, newItem) {
        cb(newItem);   
    }); 
});

Upvotes: 2

broofa
broofa

Reputation: 38132

The problem isn't variable scope, it's that async.queue doesn't know about all the async functions you're scheduling. Specifically, it doesn't know about the item.save() calls - it only knows about the outer function that schedules item.save(). The actual save and resulting callback invocation are done asynchronously, after drain() has been called, which is why itemIds appears empty. (Make sense?)

To solve this, I would suggest you use the Step module instead of async. Specifically, look at Step's group() feature, which allows you to indicate when nested asynchronous control flows like this have finished.

Upvotes: 1

Related Questions