This workshop has been inspired by Eoin McCarthy and his legendary waterfall function workshop given to FAC9 by Besart Hoxhaj.
You may have seen the compose function before, it allows you to take some functions and compose them into a single function! What do you do if the functions are asynchronous? You implement the waterfall function.
Like the compose function, the waterfall function runs an array of functions in series, each passing their result to the next function in the array. Crucially, the waterfall function will not invoke the next function in the array until the current function being run has been returned.
The waterfall function takes three arguments:
-
An initial argument, this is passed into the first async function in the waterfall.
-
The second argument is an array of functions, each function takes two arguments. The first argument it uses to find a result and the second is a callback function.
-
A final callback is given as the third argument. This is called after the waterfall has invoked all of the functions in the array.
-
Copy the code below and paste it into Repl.
-
Create the waterfall function, pass the tests.
-
For bonus points, create some additional tests for the waterfall function.
function asyncAddOne(x, callBack) {
setTimeout(function() {
if (typeof x !== 'number'){ return callBack(new Error('need a number!')) }
else { return callBack(null, x + 1) }
}, 200)
}
function asyncDouble(x, callBack) {
setTimeout(function() {
if (typeof x !== 'number') { return callBack(new Error('need a number!')) }
else { return callBack(null, x * 2) }
}, 200)
}
function asyncTimesTen(x, callBack) {
setTimeout(function() {
if (typeof x !== 'number') { return callBack(new Error('need a number!')) }
else { return callBack(null, x * 10) }
}, 200)
}
// Create this function!
function waterfall(arg, tasks, cb) {
cb(new Error('waterfall function not implemented'));
}
waterfall(3, [
asyncAddOne,
asyncDouble,
asyncTimesTen
], function(error, result) {
console.log('Test 1');
if (error) {
console.log('test failed, ' + error)
}
else if (result !== 80) {
console.log('test failed, expected 80 but got', result)
}
else {
console.log('Test 1 passed!')
}
})