What is the difference between async.waterfall and async.series

Javascriptnode.jsAsynchronousNode Async

Javascript Problem Overview


The nodejs async module: https://github.com/caolan/async provides 2 similar methods, async.waterfall and async.series.

What is the difference between them?

Javascript Solutions


Solution 1 - Javascript

It appears that async.waterfall allows each function to pass its results on to the next function, while async.series passes all results to the final callback. At a higher level, async.waterfall would be for a data pipeline ("given 2, multiply it by 3, add 2, and divide by 17"), while async.series would be for discrete tasks that must be performed in order, but are otherwise separate.

Solution 2 - Javascript

Both functions pass the return value, of every function to the next, then when done will call the main callback, passing its error, if an error happens.

The difference is that async.series(), once the series have finished, will pass all the results to the main callback. async.waterfall() will pass to the main callback only the result of the last function called.

Solution 3 - Javascript

async.waterfall() is dealing with an action that relies on the previous outcome.

async.series() is dealing with an action that wants to see all the result at the end

Solution 4 - Javascript

I consider async.waterfall to be harmful, because it's hard to refactor once written and also error-prone since if you supply more arguments, other functions much change the signature.

I highly recommend async.autoInject as a great alternative, to async.waterfall. https://caolan.github.io/async/autoInject.js.html

If you do choose to use async.waterfall, I recommend storing everything in one object, so your functions don't have to change length/signatures, like so:

warning: this is a bad pattern

async.waterfall([
  cb => {
    cb(null, "one", "two");
  },
  (one, two, cb) => {
    cb(null, 1, 2, 3, 4);
  },
  (one,two,three,four,cb) => {
     // ...
  }
])

don't do it the above way. This is a much better pattern to use:

async.waterfall([
  cb => {
    cb(null, {one:"one", two:"two"});
  },
  (v, cb) => {
    cb(null, [1, 2, 3, 4]);
  },
  (v,cb) => {
     // ...
  }
])

that way you won't pull your hair out trying to make sure the function arguments have the right length. The first function only accepts one arg - callback. All the remaining ones should accept two arguments - a value and callback. Stick to the pattern and you will remain sane!

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBruce DouView Question on Stackoverflow
Solution 1 - JavascriptTwisolView Answer on Stackoverflow
Solution 2 - Javascriptuser1598585View Answer on Stackoverflow
Solution 3 - JavascriptWayne ChiuView Answer on Stackoverflow
Solution 4 - JavascriptAlexander MillsView Answer on Stackoverflow