Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a loop of promises

so i have a promise that collects data from a server but only collects 50 responses at a time. i have 250 responses to collect.

i could just concate promises together like below

new Promise((resolve, reject) => {
    resolve(getResults.get())
    })
    .then((results) => {
    totalResults.concat(results)
    return getResults.get()
    })
    .then((results) => {
    totalResults.concat(results)
    return getResults.get()
    }).then((results) => {
     totalResults.concat(results)
    return getResults.get()
    })

In this instance i only need 250 results so this seems a managable solution but is there a way of concating promises in a loop. so i run a loop 5 times and each time run the next promise.

Sorry i am new to promises and if this were callbacks this is what i would do.

like image 413
Susan Ho Avatar asked Mar 19 '17 14:03

Susan Ho


People also ask

Can promises resolve multiple times?

No. It is not safe to resolve/reject promise multiple times. It is basically a bug, that is hard to catch, becasue it can be not always reproducible.

How do you run a promise in series?

The Promise. resolve() method executes the first callback, and when this promise is fulfilled, then it passes to the next function callback1, and it goes on until all the promises are fulfilled. In this way, we can run all the Promises in series.

Does promise run in parallel?

Unlike callbacks, which are always executed sequentially (one after another), you have options for how to run multiple promises. Promises provide you with several options for how you can run promises in parallel.

How does promise work in event loop?

A promise represents the completion of an asynchronous function. It is an object that might return a value in the future. It accomplishes the same basic goal as a callback function, but with many additional features and a more readable syntax.


1 Answers

If you want to loop and serialise the promises, not executing any other get calls once one fails, then try this loop:

async function getAllResults() {  // returns a promise for 250 results
    let totalResults = [];
    try {
        for (let i = 0; i < 5; i++) {
            totalResults.push(...await getResults.get());
        }
    } catch(e) {};
    return totalResults;
}

This uses the EcmaScript2017 async and await syntax. When not available, chain the promises with then:

function getAllResults() {
    let totalResults = [];
    let prom = Promise.resolve([]);
    for (let i = 0; i < 5; i++) {
        prom = prom.then(results => {
            totalResults = totalResults.concat(results);
            return getResults.get();
        });
    }
    return prom.then(results => totalResults.concat(results));
}

Note that you should avoid the promise construction anti-pattern. It is not necessary to use new Promise here.

Also consider adding a .catch() call on the promise returned by the above function, to deal with error conditions.

Finally, be aware that concat does not modify the array you call it on. It returns the concatenated array, so you need to assign that return value. In your code you don't assign the return value, so the call has no effect.

See also JavaScript ES6 promise for loop.

like image 115
trincot Avatar answered Oct 06 '22 17:10

trincot