jWorkflow: A JavaScript Workflow Framework

Dude Where’s my workflow?

While working on large javascript projects at tinyHippos we would commonly end up with a rather complex bootstrapping process where we need to execute a large amount of initialization code in a specific order. Some of this code is asynchronous and some is synchronous.

We would start out with a series of events and function calls to attempt to chain together the bootup but it would quickly become hard to inject in new tasks. This prompted us to use the tinyHippos mantra “There has to be a better way”.

A framework is born

Sitting around talking about what we would need to do to fix our bootstrapping problems we settled on a workflow system that would allow us to chain the initialization functions together to run in a specific order. The team kept throwing around ideas as to what the API look like and how to use it when we remembered a quote from a movie we all loved that inspired the API for our framework:

After some laughing we sat down and started hacking in VIM to iron out the interface. We ended up with this example that drove the rest of the design:

var foooodOrder = jWorkflow.order(garlicChicken)
    .andThen(whiteRice)
    .andThen(wontonSoup)
    .andThen(cookiesFortune);
    .andThen(noAndThen)
    .andThen(noAndThen);

foooodOrder.start();

From there we could start thinking about supporting asynchronous calls (the main reason we needed this framework). I had just started reading Beautiful Code (Beautiful Code: Leading Programmers Explain How They Think) and the chapter on SVNs Delta Editor interface had an awesome concept where they would pass a baton to control the flow of the tree recursion. This lead to the following function signature:

function procrastinate(previous, baton) {
    //take the baton, this means the next task will not run until you pass the baton
    baton.take();

    window.setTimeout(function() {
        //do some stuff
        //NOTE: previous contains the return value of the previous task

        //please be nice and always remember to pass the baton!
        baton.pass();
    }, 1000);
}

We could then allow the function to step into the workflow and control when the handoff to the next task happens with a small amount of code. They could also just ignore this parameter if they don’t need it and just return from their function as they normally would:

function dude() {
    return 42; //this will be passed to the next function in the workflow
}

Introducing jWorkflow

Once we had the outline of the API to code against, I went off that night and coded up the framework. The next day we were able to plug it into our bootstrapping and clean up some of the broken windows in our code.

We are releasing jWorkflow under the MIT license and we hope you enjoy it. You can find it on github at: http://github.com/tinyhippos/jWorkflow.

About these ads

2 Responses

  1. Seems interesting, jWorkflow is opensource so do a pull request on:
    https://github.com/tinyhippos/jWorkflow

    I want to see how this runs.

    Thanks for the interest!

  2. I think you can replace the baton.take and baton.pass stuff with a little reflection:

    if (task.func.length == 2) {
    result = task.func.apply(task.context, [result, _baton]);
    } else {
    result = task.func.apply(task.context, [result]);
    _baton(result);
    }

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: