Async: Feature/support - Empty taskset -> final callback automatically fired on next tick?

Created on 13 Apr 2017  ·  3Comments  ·  Source: caolan/async

Say we are using async.map or really almost any of the async utilities

My question/feature request is - if the task array/set is empty, does async fire the final callback on the next tick? If not, is there a way to tell async to do that? Would be a nice feature.
Otherwise, I have a lot of this in my code, which is more verbose:

async.map([], function(item,cb){

}, function final(err, results){
    process.next(function(){ 
      cb(err,results);
   });
});

to avoid Zalgo, this above is necessary, but, it is a lot nicer to do:

async.map([], function(item,cb){

}, cb);

I guess one thing we could is check if the array is empty, and if so, return early with

if(![].length){
   return process.next(cb);
}

what do yall recommend?

question

Most helpful comment

Yep, @hargasinski has it on the money. We do not protect you from Zalgo for performance reasons.

One simplification you can do is:

function final(err, results){
    process.nextTick(cb, err, results);
}

async.nextTick/async.setImmediate/process.nextTick/setImmediate all let you pass args that will be passed to the function.

All 3 comments

Hey @ORESoftware, thanks for the question! For an empty array/set, async invokes the final callback on the same tick as built-in deferrals were removed in v2.0.0 for performance reasons (I don't think async < v2.0.0 even had a built-in deferral for this case though).

A simple workaround is wrapping async.map in async.ensureAsync:

async.ensureAsync(async.map)([], function(item, cb) {

}, cb);

or somewhere at beginning of your code:

const asyncMap = async.ensureAsync(async.map);
// then call `asyncMap` just as you would `async.map`

Otherwise, the process.nextTick approach you proposed is perfectly valid. Although, if you are writing code that might get used in a browser, you should take a look at async.setImmediate or async.nextTick.

Yep, @hargasinski has it on the money. We do not protect you from Zalgo for performance reasons.

One simplification you can do is:

function final(err, results){
    process.nextTick(cb, err, results);
}

async.nextTick/async.setImmediate/process.nextTick/setImmediate all let you pass args that will be passed to the function.

Oh nice, I did not know that about process.nextTick, etc, that's awesome

Was this page helpful?
0 / 5 - 0 ratings