3

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.

Merc
  • 16,277
  • 18
  • 79
  • 122

1 Answers1

5

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.

slebetman
  • 109,858
  • 19
  • 140
  • 171
  • 1
    AAaaaahhhhhhhhhhhhhhh I get it, 100%. Wow, _thank_ _you_. My little head wa stuck thinking that the `next` parameter had to be the next callback... but OF COURSE NOT! It needs to be a quick function that simply continues the job! So obvious once you see it... thank you! – Merc Nov 28 '12 at 10:59
  • 1
    It does take some getting used to writing event oriented code. But once you get used to passing and returning functions (and I mean be really comfortable with it, not just understand it) everything sorts of makes sense and you stop thinking in terms of if..else and loops. – slebetman Nov 28 '12 at 14:46
  • 1
    Any hints to speed up the "getting comfortable it" phase? I feel I am really struggling with it... – Merc Nov 28 '12 at 16:01
  • 1
    Just the usual 10000 hours rule. It also helps if your lecturers taught you Lisp or Haskell on college (mine didn't unfortunately). Just keep coding and read other people's code. It's like how we learn spoken languages. When we start learning a language we often don't get jokes in that language. Then at one point we understand it well enough and start to laugh. – slebetman Nov 28 '12 at 16:21
  • I never studied lisp nor Haskell, now I see the point... maybe I should just learn them? Or, is there a resource somewhere that explains the common "patterns", so that my brain is gracefully taught how to think in terms of async functions? I am very comfortable with passing and returning functions, it's just that I am stuck in the thiking in terms of loops and ifs... – Merc Nov 29 '12 at 01:08