I am trying to work with async in node js, to control the flow of execution of some functions. In the code below I have three declared functions that should print respectively 'one', 'two' and 'three', along with performing other tasks (the printing is only so that I can see what gets executed when).
async.waterfall([
function(callback) {
settings();
console.log("1");
callback(null, 'one');
},
function(callback) {
profile();
console.log("2");
callback(null, 'two');
},
function(callback) {
console.log("3");
groups();
callback(null, 'two');
}
]);
So I get the error "callback is not a function" in the line of callback(null, 'two'); To be honest, this might as well be a very dummy question, and I do not fully understand how async waterfall works. But I seriously did try, by reading examples, trying to implement short code and trying to play around with it.
Interesting that if async.series is used instead of async.waterfall, there is no such error. However async.series will print 1, 2, 3, three, one, two. The numbers inside the waterfall model are printed in sequence, but the functions inside are not executed in the right order.
It is to be noted that the first two functions - settings and profile - include db reading and calculations whereas the third only prints some results.
I am trying to work with async in node js, to control the flow of execution of some functions. In the code below I have three declared functions that should print respectively 'one', 'two' and 'three', along with performing other tasks (the printing is only so that I can see what gets executed when).
async.waterfall([
function(callback) {
settings();
console.log("1");
callback(null, 'one');
},
function(callback) {
profile();
console.log("2");
callback(null, 'two');
},
function(callback) {
console.log("3");
groups();
callback(null, 'two');
}
]);
So I get the error "callback is not a function" in the line of callback(null, 'two'); To be honest, this might as well be a very dummy question, and I do not fully understand how async waterfall works. But I seriously did try, by reading examples, trying to implement short code and trying to play around with it.
Interesting that if async.series is used instead of async.waterfall, there is no such error. However async.series will print 1, 2, 3, three, one, two. The numbers inside the waterfall model are printed in sequence, but the functions inside are not executed in the right order.
It is to be noted that the first two functions - settings and profile - include db reading and calculations whereas the third only prints some results.
Share Improve this question asked Oct 26, 2016 at 18:24 Lazarus RisingLazarus Rising 2,6858 gold badges35 silver badges61 bronze badges 1-
This problem occurs when you nest
async
calls, particularly if you call anasync.series
inside of anasync.waterfall
, or vice-versa,async
will bee unreliable. – Sandwich Commented Oct 3, 2017 at 16:32
5 Answers
Reset to default 6With async.waterfall
, results are passed to the next function as arguments. For 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'
});
In your case, callback
on the second function will have received the string one
as argument. And thus the error you are experiencing.
To make it simplified, callback(null, 'one')
means you pass one argument to next. Meaning your function need to accept 1 parameter in front of callback.
callback(null, 'one')
follows by function(arg1, callback)
where arg1 = 'one'
callback(null, 'one', 'two')
follows by function(arg1, arg2, callback)
where arg1='one'
and arg2='two'
async.waterfall([
function(callback) {
settings();
console.log("1");
callback(null, 'one');
},
function(arg1, callback) {
profile();
console.log("2");
callback(null, 'two');
},
function(arg1, callback) {
console.log("3");
groups();
callback(null, 'two');
}
]);
Waterfall
First of all I advice you to use Async auto in place of waterfall model the reason behind this is in waterfall model we will be moving one by one like first we will finish the execution of 1st function then move on to second then 3rd i.e we will go in a series no matters weather our function are dependent on each other or not
Auto
Benefits of auto are that it doesn't really matters weather your functions are dependent on each other as auto can run tasks in series (for dependent functions) and parallel (for the functions which are not dependent on each other)
async.auto({
get_data: function(callback) {
console.log('in get_data');
callback(null);
},
make_folder: function(callback) {
callback(null);
},
write_file: ['get_data', 'make_folder', function(results, callback) {
callback(null);
}],
email_link: ['write_file', function(results, callback) {
callback(null);
}]
}, function(err, results) {
});
here in above example we have get_Data function and make_folder function which are not dependent on each other so we can run them parallel and by passing the name of get_Data & make_folder we can restrict out write_file function to run only after both of above function get executed.
for more details you can visit http://caolan.github.io/async/docs.html#auto
even have a look on async.autoInject it have recently been added to async in place of auto. but auto will continue for precious versions of async
This is not right way to use
waterfall
try to pass another parameters in functions and put last parameter as callback.
async.waterfall([
function(callback) {
settings();
console.log("1");
callback(null, 'one');
},
function(previous_value,callback) {
profile();
console.log("2");
callback(null, 'two');
},
function(previous_value,callback) {
console.log("3");
groups();
callback(null, 'two');
}
], function(err,result){console.log(result)});
You also forgot to pass final callback after all the execution.
The async waterfall callback and the order of the method should be matched to work correctly. I had the same problem due to the incorrect method orde. your callback parameters and the next function's parameters should be matched to work. please refer to the below example.
async.waterfall([
myFirstFunction,
mySecondFunction,
myLastFunction,
], function (err, result) {
// result now equals 'done'
});
function myFirstFunction(callback) {
callback(null, 'one', 'two');
}
function mySecondFunction(arg1, arg2, callback) {
// arg1 now equals 'one' and arg2 now equals 'two'
callback(null, 'three');
}
function myLastFunction(arg1, callback) {
// arg1 now equals 'three'
callback(null, 'done');
}
In the async.waterfall array you can specify the order of the methods. follow the documentation for more examples.