Friday, June 15, 2012

How to use named functions with Async waterfall in node.js

Lets start with a real world example where you want to create a user in CouchDB. This is a two step process that involves asking for a unique uuid and then creating a user based on that.
  • The following code (+/-) abstracts out each individual step:
    function getUUID() {
    nano.request(
    {
    method : 'GET',
    path : '_uuids?count=1'
    },
    function (err, body, headers) {
    if (err) {
    console.error(err);
    } else {
    console.log(body.uuids[0]);
    }
    }
    );
    }
    function createUser(uuid) {
    var usersDB = nano.db.use('_users');
    usersDB.insert(
    {
    'name' : uuid,
    'password' : 'pwdUser1',
    'roles' : [],
    'type' : 'user'
    },
    'org.couchdb.user:'+ uuid,
    function(err, body, header) {
    if (err) {
    console.error('[_users.insert] ', err);
    } else {
    console.log('you have inserted the uuid.')
    console.log(body);
    }
    }
    );
    }
  • But once you have the abstracted methods, how do you chain their results? This is where the waterfall approach from the Async NPM package comes in.
  • Since you've already abstracted your methods, you may try something like this (+/-) to make them a little more waterfall friendly:
  • And then you may try the simplest way you can think of asking waterfall to run:
  • But that will fail to run because the syntax of the sentence has ended up being written in a manner where callback must be a variable that is already defined and ready to be used. Making an anonymous method here and bringing up the entire code bodies of the abstracted named-methods would defeat the readability and reuseability that we have been trying to achieve. Here's a tweak that will make it happen:

3 comments:

  1. Or you could just pass the functions as variables..

    // Works
    async.waterfall([
    getUUID,
    createUser
    ],
    function (err, result) {
    console.log(result);
    }
    );


    Error in your first thought solution is that the functions get called in place since you pass params to them.

    // Does not work
    async.waterfall(
    [
    getUUID (callback),
    createUser(uuid, callback)
    ],
    function (err, result) {
    console.log(result);
    }
    );

    Other then that, thank you very much!

    ReplyDelete
  2. Thanks for posting this, I found the example in the Github readme a little confusing, but this cleared it up!

    ReplyDelete