node package manager

heavy-flow

An async flow-control library

HEAVY FLOW

A dead-simple asynchronous flow control library, meant for use with NodeJS or browsers.

Why?

It's simple, small, and readable by virtue of being only vaguely Promise-based. It solves the brittle callback nightmare of this:

asyncFn1(err, data) {
    asyncFn2(err, data) {
        asyncFn3(err, data) {
            // ... 
        }
    }
}

...but doesn't need bunches of when/then/parallel/etc. functions to do independent asynchrony or manage dependencies. All it uses is a wait() function and a callback, although it throws in some nice chained finished() and cancelled() callbacks to make success, exception, and error handling easier. And it's heavily tested, to boot.

WATCH THIS

var flow = require('./heavy-flow');
 
// this is dependent on nothing. it'll start executing immediately. 
var async1 = flow.wait(function(finish, cancel) {
    asyncFn(function(err, data) {
        if(err) cancel(err);
        else finish(data);
    });
});
 
// this is dependent on async1. it'll start it's ready function as soon as 
// async1 finishes. if async1 or async2 cancels, it'll execute it's cancelled 
// function. 
var async2 = flow.wait(async1, function(finish, cancel) {
    dependentAsyncFn(function(err, data) {
        if(err) cancel(err);
        else finish(data);
    });
}).cancelled(function(err) {
    console.log("this one didn't make it.");
});
 
// this isn't dependent on anything, so it'll also start executing it's ready 
// function immediately. the function inside might not be asynchronous -- if it's 
// synchronous, it'll finish (or cancel, if there's an error) immediately, and run 
// it's finished() callback if successful. 
var async3 = flow.wait(function(finish, cancel) {
    iDontEvenKnowIfThisIsAsynchronousButItKindaLooksLikeIt(function(err, data) {
        if(err) cancel(err);
        else finish(data);
    });
}).finished(function() {
    console.log("a glorious victory.");
});

DOCS

Wait Objects

Everything in Heavy Flow is based around wait objects. Wait objects are units of asyncronous flow -- they'll run asynchronously as soon as they're able to, and notify anything that depends on them to run once they're finished.

Wait objects have the following accessors:

  • waitObject.data() returns any data saved from the asynchronous operation.
  • waitObject.isFinished() returns whether the wait object has finished.
  • waitObject.isCancelled() returns whether the wait object has cancelled.

Wait objects also can be assigned the following callbacks:

  • waitObject.finished(callback), where callback is a function of the form function(data). This assigns a callback to the wait object that will be called immediately if the wait object's asycnhronous operation finishes successfully.
  • waitObject.cancelled(callback), where callback is a function of the form function(err). This assigns a callback to the wait object that will be called immediately if the wait object's asycnhronous operation cancels, instead of finishing.

Creating wait objects is simple:

  • flow.wait(dependencies..., callback), where dependencies are any wait objects that need to finish prior to this one running, and callback is a function that performs something asynchronous once all of the dependencies are satisfied. Dependencies may either be an argument list or an array. If no dependencies are given, the callback runs immediately. callback should be of the form function(finish, cancel), where finish is a function you call if the asynchronous operations were a success, and cancel is the function you call if the asynchronous operations were unsuccessful.

Both finish and cancel can be called with an argument -- in finish's case, whatever is passed in gets set as the object's data property, and in cancel's case, it passes that argument along as the error message for any cancelled callbacks.