Doing a series of asynchronous operations in node.js

What is a good way of doing a series of asynchronous operations in Node.js? This is for a script type of application, an application that is supposed to be run from the command line and then finish a job, it is not in the context of a server that should sit in the background and handle several different things at once.

I know of Promises/A+ aka Thenables, but the syntax doesn't get that nice:

do_some_stuff().then(
   function() {
       do_some_other_stuff().then(
           function() {
               do_the_last_stuff().then(
                   function() {
                      // we are done with everything!
                   }
               )
           }
       )
   }
);

When we have more operations the indentation will make it look quite ugly.

I like how jasmine does it, where the asynchronous operation gets passed a function that it should call when it is finished. Based on this idea, I created something I called AsyncSequence. The AsyncSequence runs a series of operations, and each operation gets passed a done function that should be called on completion. Using AsyncSequence the above would look like:

AsyncSequence.run(
    function(done) {
        do_some_stuff().then(done);
    },
    function(done) {
        do_some_other_stuff().then(done);
    },
    function(done) {
        do_the_last_stuff().then(done);
    },
    function() {
        // we are done with everything!
    }
);

This works and it looks nicer I think, but I wonder if there is a more "standard" way of doing it? Is there something similar to my AsyncSequence that comes to mind when you seasoned Node.js programmers see this? Or something that is not exactly similar, but can be used for the same purpose?

With Promises/A+, then can be chained, making your first example:

do_some_stuff()
.then(do_some_other_stuff)
.then(do_the_last_stuff)
.then(function() {
  // we are done with everything!
});

Looking at a promise as a container for a value you will have in the future, then transforms the future value into another value (kind of like [].map). But if the function you pass to then returns another promise, it gets unwrapped. For a more concrete example:

getPostData(req).then(function(data) {
  return createNewUser(data);
}).then(function(user) {
  return JSON.stringify(user);
}).then(function(json) {
  return successResponse(json);
}).then(function(body) {
  res.end(body);
});

This example uses explicit function parameters to make the flow a bit more obvious. createNewUser returns a promise representing the User object as saved to the database, whereas JSON.stringify of course just returns a String. Promises/A+ can handle and chain both kinds of return value.

Use the async module. See watefall method. https://github.com/caolan/async

async.waterfall([
    function(callback){
        callback(null, 'one', 'two');
    },
    function(arg1, arg2, callback){
      // arg1 now equals 'one' and arg2     now equals 'two'
        callback(null, 'three');
    },
    function(arg1, callback){
        // arg1 now equals 'three'
        callback(null, 'done');
    }
], function (err, result) {
   // result now equals 'done'    
});