递归Promise.all?

时间:2016-06-29 18:09:46

标签: javascript async-await ecmascript-6 es6-promise

我试图等待一堆承诺完成。我知道我可以用Promise.all做到这一点,但是当其中一个承诺将新承诺推入承诺列表时,我无法弄清楚要做什么。

示例:

asyncFunction(...).then(result => {
    // do something
});


asyncFunction(...).then(result => {
    for(let row of result) {
        asyncFunction(row);
    }
});


console.log(promises.length); // 2
await Promise.all(promises);
console.log(promises.length); // 5

asyncFunction类似于:

const asyncFunction = (...args) => {
    let result = new Promise((resolve, reject) => {
        pool.query(...args, (err, rows, fields) => {
            if (err) {
                reject(err);
            } else {
                resolve(rows); 
            }
        });
    });
    promises.push(result);
    return result;
};

这里发生的事情是前两次调用asyncFunction将promises推送到我的promises数组中,因此promises.length为2.但是,在等待它们完成之后在Promise.all已经评估过该数组之后,第二个将一堆新的promises推入数组中,所以他们不会等待它们。

那么,我怎么能等待所有的承诺,再加上任何新承诺?只需拨打await Promise.all(promises)两次就可以在这个例子中使用,但这可以无限制地进行。

3 个答案:

答案 0 :(得分:4)

您可以编写一个递归的all函数,在每次迭代后重新计算列表的状态:

function recursiveAll( array ) {
    // Wait for the promises to resolve
    return Promise.all( array ).then(function( result ) {
        // If no new promises were added, return the result
        if ( result.length == array.length )
            return result;
        // If new promises were added, re-evaluate the array.
        return recursiveAll( array );
    });
}

答案 1 :(得分:2)

这是带有副作用的功能的问题。

您的代码有点抽象,以便为您提供精确答案,但我建议您完全删除promises - 数组。

const asyncFunction = (...args) => {
    return new Promise((resolve, reject) => {
        pool.query(...args, (err, rows, fields) => {
            if (err) {
                reject(err);
            } else {
                resolve(rows); 
            }
        });
    });
}

asyncFunction(...).then(result => Promise.all(result.map(row => asyncFunction(row))) );

据我了解你的意图,这应该导致阵列中阵列的嵌套结构,在最坏的情况下,现在只需要展平以获得所有值,以及那些由之前的值触发的值。

答案 2 :(得分:0)

我认为用这个替换Promise.all应该可以正常工作:

while(promises.length) {
    await promises.shift();
}