What is a simple implementation of async.waterfall?

I use some functions from the asynchronous library and want to make sure that I understand how they do things internally; however I am stuck on async.waterfall ( implementation here ). The actual implementation uses other functions from the library and without much experience, it is difficult for me to follow.

Can someone, without worrying about optimization, provide a very simple implementation that ensures the functioning of the waterfall? Probably something comparable to this answer .

From documents , description of the waterfall:

Starts an array of tasks from functions sequentially, each of which passes their results followed in an array. However, if any of the tasks passes errors to their own callback, the next function is not executed, and the main callback is immediately called with an error.

Example:

 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' }); 
+6
source share
2 answers

Well, here is a simple implementation for a chain of functions, queuing them up.

First of all, the function:

 function waterfall(arr, cb){} // takes an array and a callback on completion 

Now we need to track the array and repeat it:

 function waterfall(arr, cb){ var fns = arr.slice(); // make a copy } 

Let's start by processing the passed and empty array by adding an additional parameter so that we can pass the results around result :

 function waterfall(arr, cb, result){ // result is the initial result var fns = arr.slice(); // make a copy if(fns.length === 0){ process.nextTick(function(){ // don't cause race conditions cb(null, result); // we're done, nothing more to do }); } } 

Which is nice:

 waterfall([], function(err, data){ console.log("Done!"); }); 

Now, they say, actually the handle in the file:

 function waterfall(arr, cb, result){ // result is the initial result var fns = arr.slice(1); // make a copy, apart from the first element if(!arr[0]){ // if there is nothing in the first position process.nextTick(function(){ // don't cause race conditions cb(null, result); // we're done, nothing more to do }); return; } var first = arr[0]; // get the first function first(function(err, data){ // invoke it // when it is done if(err) return cb(err); // early error, terminate entire call // perform the same call, but without the first function // and with its result as the result waterfall(fns, cb, data); }); } 

And this! We overcome the fact that we cannot iterate over calls using recursion basically. Here is a script illustrating this.

It is worth noting that if we implemented it using promises, we could use a for loop.

+8
source

For those who like to keep it short:

 function waterfall(fn, done){ fn.length ? fn.shift()(function(err){ err ? done(err) : waterfall(fn, done) }) : done(); } 
0
source

Source: https://habr.com/ru/post/983450/


All Articles