用于使用异步函数进行迭代

时间:2014-08-25 15:20:23

标签: javascript node.js

我使用for for each来处理列表,我希望只有在元素n-1结束时才执行元素n:

var elements = ["stuff1", "stuff2", "stuff3"];

elements.forEach(function(element){
    someAsyncFunction(element, function(){
       console.log('do more stuff');
   });
});

我需要他们彼此等待并以正确的顺序执行。

编辑:我碰到了process.nextTick(),但我不确定它是否能保证等待和订购。

2 个答案:

答案 0 :(得分:4)

只需将元素存储在数组中,就像在问题中一样。然后使用elements.shift()检索并删除第一个元素。

var elements = ["stuff1", "stuff2", "stuff3"];
(function next () {
    if (!elements.length) {
        return;
    }

    var element = elements.shift();
    someAsyncFunction(element, function (err, result) {
        …
        next();
    });
})();

答案 1 :(得分:2)

一种不错的方法是使用诸如QBluebird之类的承诺库,然后实施promiseWhile like this

var Promise = require('bluebird');

var promiseWhile = function(condition, action) {
    var resolver = Promise.defer();

    var loop = function() {
        if (!condition()) return resolver.resolve();
        return Promise.cast(action())
            .then(loop)
            .catch(resolver.reject);
    };

    process.nextTick(loop);

    return resolver.promise;
};

用法:

var sum = 0,
    stop = 10;

promiseWhile(function() {
    // Condition for stopping
    return sum < stop;
}, function() {
    // Action to run, should return a promise
    return new Promise(function(resolve, reject) {
        // Arbitrary 250ms async method to simulate async process
        // In real usage it could just be a normal async event that 
        // returns a Promise.
        setTimeout(function() {
            sum++;
            // Print out the sum thus far to show progress
            console.log(sum);
            resolve();
        }, 250);
    });
}).then(function() {
    // Notice we can chain it because it's a Promise, 
    // this will run after completion of the promiseWhile Promise!
    console.log("Done");
});