问题
When using async.waterfall within a for
loop, it appears that the for
loop iterates before the nested async.waterfall
finishes all its steps. How can this be avoided?
for(var i = 0; i < users.length; i++ ) {
console.log(i)
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'
console.log('done')
});
}
Output
0
1
2
3
4
done
done
done
done
done
Desired Output
0
done
1
done
2
done
3
done
4
done
回答1:
You can use like this with async's forEachLimit
var async = require("async")
var users = []; // Initialize user array or get it from DB
async.forEachLimit(users, 1, function(user, userCallback){
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'
console.log('done')
userCallback();
});
}, function(err){
console.log("User For Loop Completed");
});
回答2:
You would need to apply a recursive pattern. My suggestion would be something like this
function foo(properties, callback){
/*Initialize inputs w/ useful defaults. Using a properties object simply because it looks nicer, you can use individual values if you'd like.*/
properties.start = properties.start || 0;
properties.end = properties.end || 10; //or any default length
properties.data = properties.data || [];
async.waterfall([
function(callback) {
},
function(arg1, arg2, callback) {
/* arg1 now equals 'one' and arg2 now equals 'two' you can do something with that before continuing processing */
},
function(arg1, callback) {
/* arg1 now equals 'three', you can do something with that before continuing processing */
}
], function (err, result) {
// result now equals 'done'
// now that we have fully processed one record, we need to either finish or recurse to the next element.
if(properties.index >= properties.end){
callback();
}
else{
properties.index++;
foo(properties, callback);
}
})}
I've passed the callback into each of the function callbacks. You could chose to end the recursion early this way if you wanted to, or you could do anything elsein that spot that you wanted to. This is similar to a question that I asked recently: Patterns for asynchronous but sequential requests which has some other interesting solutions to the problem as well.
来源:https://stackoverflow.com/questions/31799175/async-waterfall-in-a-for-loop-in-node-js