I want to iterate an array asynchronously to unblock the execution. I'm using caolan/async to achieve that. When testing this code:
var ASync = require('async');
var arr = [];
for (var i = 0; i< 10; i++) {
arr[i] = i;
}
var buf = "howdy";
ASync.forEach(arr, function(item, callback) {
buf += item;
callback();
}, function(err) {
console.log(buf); // in the end
});
buf += "finished";
it shows this result:
howdy0123456789
I would assume it should show
howdyfinished0123456789
since I expect the Async lib to defer the execution. But why it isn't?
In your code, callback
is executed on the same event loop iteration as foreach
itself. As you never go outside of the current event loop iteration, buf += "finished"
only executes after all buf += item
were executed.
The proper version is
var ASync = require('async');
var arr = [];
for (var i = 0; i< 10; i++) {
arr[i] = i;
}
var buf = "howdy";
ASync.forEach(arr, function(item, callback) {
process.nextTick(function () {
buf += item;
callback();
});
}, function(err) {
console.log(buf); // in the end
});
buf += "finished";
In the end, the buf
will equal to howdy0finished123456789
.
However, this task is oversimplified. Why does one need the async loop at all?
To perform async tasks in parallel. First, as each task is async, you won't trigger the callback
in the same event loop iteration anyway, rather giving it to the specific async task. Second, async.parallel
is more suitable for this kind of task.
To perform some CPU-intensive tasks, avoiding freezing the event loop (so that Node could process some tasks in between the iterations). This is what I'm assuming in my code example above. It would be quite hard to achieve this task using the plain JS (and its build-in Array.prototype.forEach
), as you need to implement in some way the detection of the event all iterations of the loop has been processed.
I think you should read this: http://howtonode.org/understanding-process-next-tick