Reputation: 995
I have two (or more) asynchronous functions - say f1(param,callback)
and f2(param,callback)
which I want to run in sequence, i.e. I first execute f1
and when completed, I then execute f2
(with the result of f1
). This can go on, with f3
being executed after f3
. An use case would be that f1
does some processing and f2
can either be the display of the result or further processing. I'm wondering what is the "cleanest" approach to implement that. I was thinking about asyn.seq but is that really a good approach? Any sample code?
This is the code I was thinking of:
var obj = {"start": "an empty objet"};
function f1(obj, callback) {
obj["f1"] = "item added by f1";
callback(null, obj);
}
function f2(obj, callback) {
obj["f2"] = "item added by f2";
callback(null, obj);
}
function f3(obj, callback) {
obj["f3"] = "item added by f3";
callback(null, obj);
}
var seq = async.seq(f1, f2, f3)
seq(obj, function (err, result) {
log(result);
});
Upvotes: 0
Views: 721
Reputation: 111414
Note: This is the original answer for the question before it got edited. See updates below.
The cleanest way to have the result of one async function passed to the second async function would be to use async.waterfall. See:
It is created exactly for the use case that you describe - putting the resuts of one async function into the second one (and possibly more).
Example:
async.waterfall([
(cb) => f1(argForF1, cb),
f2,
], (err, result) => {
// result is the result of f2
});
the (cb) => f1(argForF1, cb)
is needed here because the first function is not called with any argument by the async.waterfall
function so you have to create a function that works like the f1
but has the argument provided already.
Maybe it's cleaner if you name that function:
let f1a = (cb) => f1(argForF1, cb);
async.waterfall([f1a, f2], (err, result) => {
// result is the result of f2
});
There are much more useful functions in the async
module, especially async.series
, async.parallel
, async.map
, async.parallelLimit
, async.mapLimit
etc. See the docs:
Originally in your question you asked what is the most elegant way to pass the result of one async function to a second async function. For that I recommended async.waterfall
. Now you edited the question and it seems that you may not need to wait for the result of one function before you run the second one after all. If that is the case then see the update below.
After you edited your question with new example, I think there is one more option to achieve what you need - if those functions can run in parallel:
Instead of this:
function f1(obj,callback){
obj["f1"]="item added by f1";
callback(null,obj);
}
function f2(obj,callback){
obj["f2"]="item added by f2";
callback(null,obj);
}
function f3(obj,callback){
obj["f3"]="item added by f3";
callback(null,obj);
}
you could change those functions to simpler ones:
function f1(callback) {
callback(null, "item added by f1");
}
function f2(callback) {
callback(null, "item added by f2");
}
function f3(callback) {
callback(null, "item added by f3");
}
and run them with async.parallel
like this:
async.parallel({f1, f2, f3}, (err, result) => {
// your result is an object
});
and have your result be an object:
{
f1: "item added by f1",
f2: "item added by f2",
f3: "item added by f3",
}
Note that it will be possible only if the functions don't need the result of the previous function - which is the case in your (newly added) examples, in which the only reason you needed the result of the previous function was to get a shared object to add a new property.
Upvotes: 1