async.waterfall in a For Loop in Node.js

耗尽温柔 提交于 2020-01-13 03:24:05

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!