Hej,
I'm experimenting with node.js and its callback mechanism. And now I wonder how to overhand data to such an anonymous callback:
var fs = require('fs');
for (var i = 0; i < 4; i++) {
console.log('Outer: ' + i);
fs.readFile('/etc/hosts', 'ascii', function(err, data) {
console.log('Inner: ' + i);
});
}
I do understand why the inner call to i returns 4 always. But how can I supply some variables to that specific readFile-callback function (so that the inner i will have the value of the outer i)? I could imagine some queue mechanism, where the callback function acts as a consumer, but as a node beginner I'd like to ask for the best practices. Thanks a lot,
mechko
With the pure Javascript (that is, not using libraries such as async):
var fs = require('fs');
var i,
reader = function (i) {
return function (err, data) {
console.log('Inner: ' + i);
}
};
for (i = 0; i < 4; i++) {
console.log('Outer: ' + i);
fs.readFile('/etc/hosts', 'ascii', reader(i));
}
Or, alternatively,
var fs = require('fs');
var i;
for (i = 0; i < 4; i++) {
console.log('Outer: ' + i);
fs.readFile('/etc/hosts', 'ascii', function (i, err, data) {
console.log('Inner: ' + i);
}.bind(null, i));
}
(moving the var i;
declaration out of the for
loop does not really changes anything in this specific example, it is just a code style to prevent the bugs related to Javascript, as opposed to the programming languages like Java, having only the function scope for variables - so that, in your original example, i
is declared for the entire module, not just for for
loop).
Alternative approach would be to use libraries such as async
and underscore
like this:
var _ = require('underscore'),
async = require('async'),
fs = require('fs');
async.parallel(_.map(_.range(0, 4), function (i) {
return async.waterfall.bind(null, [
fs.readFile.bind(null, '/etc/hosts', 'ascii'),
function (data, callback) {
console.log("Inner: " + i);
callback();
}
]);
}, function (err) {
if (err) {
console.log("Some read attempt failed");
} else {
console.log("Done reading");
}
});