Skip to content

Instantly share code, notes, and snippets.

@moechofe
Last active August 29, 2015 14:04
Show Gist options
  • Save moechofe/d9218f3edb1c9cac46fb to your computer and use it in GitHub Desktop.
Save moechofe/d9218f3edb1c9cac46fb to your computer and use it in GitHub Desktop.
A javascript helper used to call a serie of asynchronous functions passing the result from the previous one to the following

waterfall

Simple helper to call a serie of asynchronous functions. Each result from a function will be passed as arguments to the next one.

Callback use the node.js format:

  cb = function(err, result...){...}

Example with dummy asynchronous functions:

var init = waterfall([function(num,cb){

    setTimeout(function(){
        cb(null, num * 2);
    }, 1);
    
}, function(num,cb){
    
    setTimeout(function(){
        cb(null, num / 5, num * 3);
    }, 1);
 
}], function(err, result1, result2){
    
    console.log(err, result1, result2);
    
});

init(null, 123); // null 49.2 738 
init("foo", 123); // toto undefined undefined

waterfall

function init = waterfall( array funcs, function done )

Create the waterfall helper an return a function. Call it to initiate the process.

  • array funcs:

    An array of asynchronous function. See below.

  • function done:

    A callback function called when a error occure or when the last functions from funcs has finished.

  • function init:

    Return a function that initiate the process by calling the first functions from funcs.

funcs

function( ..., function next )

One of the asynchronous functions.

  • ...:

    The arbitrary list of arguments from the result of the previous function. For the very first one, the arguments come from the initiater. See below.

  • function next:

    The callback to continue calling the next asynchronous function from the list. See below.

next

function(? err, ...)

The callback passed at last argument for each asynchronous function from the list that continue the process.

  • ? err:

    To indiquate an error, a asynchronous function should call next with something for it's first argument err. It will call done by passing this err argument. See below.

    To indiquate a success, pass a null value for err argument.

    Any type can be used but remember: any different value from null will be considered as an error.

  • ...:

    The arbitrary result passed to the next asynchronous function if no error was reported. For the last asynchronous function from the list, the result will be passed to the done callback. See below.

done

function(? err, ...)

The final callback, called when the last asynchronous function from the list call it's done function, or when any asynchronous function from the list call it's done with an err argument different that null.

  • ? err:

    A asynchronous function from the list return an error.

  • ...:

    Arbitrary result from the last asynchronous function from the list.

init

function(? err, ...)

The initial function, call it to start the process.

  • ? err:

    Pass null to initiate the process.

    Pass something else will call done without calling any asynchronous function from the list

  • ...:

    The arbitrary arguments that will be passed to the first asynchronous function from the list.

/** waterfall
*
* Simple helper to call a serie of asynchronous functions.
* Each result from a function will be passed as arguments to the next one.
* Callback use the node.js format.
* Syntaxe:
* - function *init* = waterfall(array *funcs*, function *done*)
* - array *funcs* = [ function(..., function *next*), ... ]
* - function *next* = function(*err*, ...)
* - function *done* = function(*err*, ...)
* - function *init* = function(*err*, ...)
*/
var waterfall = function(funcs, cb)
{
var slicer = Array.prototype.slice;
var error = null;
var next = function(err)
{
if(err || error) return error || ((error = err) && cb && cb(err));
var func = funcs.shift();
var args = slicer.call(arguments);
if(func)
{
args.shift();
args.push(next);
func.apply(null,args);
}
else if(cb) return cb.apply(null,args);
};
return function()
{
next.apply(null,slicer.call(arguments));
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment