Reputation: 1870
I'm trying to understand async each(coll, iteratee, callback)
function to execute a function in parallel for each item of an array. From the async docs I understand that callback will be executed only once (when iteratee function will be executed for each item of the array).
And in the case of an error in the iteratee function, calling callback('some error message')
will immediately call the callback function with error message.
Below is an example from the async docs for each function
// assuming openFiles is an array of file names
async.each(openFiles, function(file, callback) {
// Perform operation on file here.
console.log('Processing file ' + file);
if( file.length > 32 ) {
console.log('This file name is too long');
callback('File name too long');
} else {
// Do work to process file here
console.log('File processed');
callback();
}
}, function(err) {
// if any of the file processing produced an error, err would equal that error
if( err ) {
// One of the iterations produced an error.
// All processing will now stop.
console.log('A file failed to process');
} else {
console.log('All files have been processed successfully');
}
});
What I'm not able to understand is, what does calling callback() without argument does, it looks very strange to me that we call callback() with no argument when there is no error in the iteratee function. What does calling callback() or callback(null)
do in case of no errors.
Can't we just remove those callback() or callback(null)
, when we actually mean to call the callback only once (when iteratee function is executed for all the elements of the array) rather than for each item of the array.
Upvotes: 0
Views: 3055
Reputation: 851
What does calling
callback() or callback(null)
do in case of no errors.
Calling callback
with no arguments or with null
signals to async.each
that the iteratee
function finished executing on that item (file
in the case of the example). When all of the iteratee
functions have called their respective callback
, or one of them passes an error to it's callback, async.each
will call the original callback
function passed to it.
To elaborate on that a little, async.js
is designed to handle asynchronous functions. The benefit (or issue, depending on how you look at it), of an asynchronous function is that there is no way to tell when it will finish executing. The way to deal with this is to pass the asynchronous function another function, a callback
, to execute when it is finished. The asynchronous function could pass any errors it encounters, or any data it retrieves, to the original calling function through the callback
function. For example, fs.readFile passes the read file data, and any errors, through the callback
function is it passed.
Can't we just remove those
callback() or callback(null)
, when we actually mean to call the callback only once (when iteratee function is executed for all the elements of the array) rather than for each item of the array.
No, because async.js
has to assume the iteratee
function is asynchorous, and therefore, it has to wait for it to its callback
. The callback
passed to async.each
is only called once.
The confusion may be caused by the variable names. An individual callback
function is only meant to be called once. The callback
function passed to async.each
is not the same callback
passed to the iteratee
. Each time iteratee
is invoked with a value in coll
, it is passed a new callback
function. That call of iteratee
is only supposed to call the passed callback
once (async
will throw an error otherwise). This allows async
to track if a call to the iteratee
function has called its callback
, and wait for the rest to call their respective callback
. Once all of the callback
functions are called, async.each
knows all of the asynchorous iteratee
function calls have finished executing, and that it can call the original callback
passed to it.
This is one of the difficult aspects of creating docs. They have to concise enough that a developer can get information from them quickly, and also include enough detail that they can explain the concept, or the function. It's a hard balance to achieve sometimes.
Upvotes: 3
Reputation: 3577
Calling callback with no arguments adds to a counter inside of the .each
function. This counter, when full is the thing that actually calls your callback. Without that, it would never know when it completed.
Upvotes: 0