最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Recursive Promise.all? - Stack Overflow

programmeradmin5浏览0评论

I'm trying to wait for a bunch of promises to plete. I know I can do this with Promise.all, but I can't figure out what to do when one of those promises pushes a new promise into the promise list.

Example:

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

Where asyncFunction is something like:

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;
};

What's happened here is that the first two calls to asyncFunction push promises into my promises array, so promises.length is 2. However, after waiting for them to plete, the 2nd one pushes a bunch of new promises into the array after Promise.all has already evaluated that array, so they're not awaited.

So, how can I wait for all the promises, plus any new ones? Simply calling await Promise.all(promises) twice would work in this example, but this could go on ad infinitum.

I'm trying to wait for a bunch of promises to plete. I know I can do this with Promise.all, but I can't figure out what to do when one of those promises pushes a new promise into the promise list.

Example:

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

Where asyncFunction is something like:

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;
};

What's happened here is that the first two calls to asyncFunction push promises into my promises array, so promises.length is 2. However, after waiting for them to plete, the 2nd one pushes a bunch of new promises into the array after Promise.all has already evaluated that array, so they're not awaited.

So, how can I wait for all the promises, plus any new ones? Simply calling await Promise.all(promises) twice would work in this example, but this could go on ad infinitum.

Share Improve this question edited Jun 29, 2016 at 18:20 mpen asked Jun 29, 2016 at 18:09 mpenmpen 284k281 gold badges892 silver badges1.3k bronze badges 6
  • 1 Don't push to the pool at arbitrary times. Wait until the pool is filled, then call Promise.all on it. Don't pool everything together in one array if you need to push at distinct times, rather call Promise.all multiple times. – Bergi Commented Jun 29, 2016 at 18:12
  • 1 @Bergi The new promises are created as a result of a previous async result. – user2864740 Commented Jun 29, 2016 at 18:15
  • 1 Does this help? – Bergi Commented Jun 29, 2016 at 18:16
  • @user2864740: So? Then those new promises should be Promise.all'd, and be chained to the previous async result via then so that you get a promise for them. – Bergi Commented Jun 29, 2016 at 18:17
  • @Bergi Yes, I think that's more or less the same question. The posted solution could probably be made slightly more efficient by not re-evaluating the already checked promises though. – mpen Commented Jun 29, 2016 at 18:24
 |  Show 1 more ment

3 Answers 3

Reset to default 5

You can write a recursive all function that re-evaluates the status of the list after each iteration:

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 );
    });
}

That's the problem with functions that have side effects.

Your code is a bit to abstract to give you a moe precise answer, but I would recend you to pletely drop the promises-Array.

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

and

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

As far as I understand your intentions, this should result in a nested structure of Arrays within Arrays, in the worst case, wich now only has to be flattened to get ALL values, and those wich are triggered by the previous ones.

I think simply replacing Promise.all with this should work fine:

while(promises.length) {
    await promises.shift();
}
发布评论

评论列表(0)

  1. 暂无评论