What is a SIMPLE implementation of async.series?

I have two functions:

function one(next){
  Users.find({}, function(err, docs){
    if( err)
      next( err );
    } else {
      next( null );
    }
  });
}

function two(next){
  Something.find({}, function(err, docs){
    if( err)
      next( err );
    } else {
      next( null );
    }
  });
}

I can use the async library:

async.series( [one, two], function( err ){
  ...
});

Here, the callback is called immediately (with err set) if one() returns err. What's an easy, BASIC implementation of async.series? I looked at the code for the library async (which is fantastic), but it's a library that is meant to do a lot of stuff, and I am having real trouble following it.

Can you tell me a simple simple implementation of async.series? Something that it will simply call the functions one after the other, and -- if one of them calls the callback with an error -- is calls the final callback with err set?

Thanks...

Merc.

One implementation would be something like this:

 function async_series ( fn_list, final_callback ) {
     // Do we have any more async functions to execute?
     if (fn_list.length) {
         // Get the function we want to execute:
         var fn = fn_list.shift();
         // Build a nested callback to process remaining functions:
         var callback = function () {
             async_series(fn_list,final_callback);
         };
         // Call the function
         fn(callback);
     }
     else {
         // Nothing left to process? Then call the final callback:
         final_callback();
     }
 }

The above code doesn't handle the processing of results or errors. To process errors we can simply check for error condition in the callback and call the final callback immediately on error:

 function async_series ( fn_list, final_callback ) {
     if (fn_list.length) {
         var fn = fn_list.shift();
         var callback = function (err) {
             if (err) {
                 final_callback(err); // error, abort
             }
             else {
                 async_series(fn_list,final_callback);
             }
         };
         fn(callback);
     }
     else {
         final_callback(null); // no errors
     }
 }

Handling results can be done similarly by either keeping track of a result array in a closure or passing it on to the next call to async_series.

Note that the final final callback can assume no errors because it arrived there via the if(err)(else)async_series call.