Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clean way to wait for first true returned by Promise

I'm currently working on something where I fire out three promises in an array. At the moment it looks something like this

var a = await Promise.all([Promise1(), Promise2(), Promise3()]); 

Now all of those promises will either return true or false. But at the moment I'm waiting for all of them to be finished and I could go on as soon as one of them returns true.

I thought of ways to accomplish that but all seem kind of ugly. How would you solve this task?

like image 578
relief.melone Avatar asked Jul 03 '18 17:07

relief.melone


People also ask

How do you wait until promise returns?

The keyword await is used to wait for a Promise. It can only be used inside an async function. This keyword makes JavaScript wait until that promise settles and returns its result.

What function will return as soon as the first promise is either fulfilled or rejected?

race() , which returns the first settled value (either fulfillment or rejection), this method returns the first fulfilled value.

How will you wait for all the promises to resolve reject that are executed inside a loop?

You can use Promise. all (spec, MDN) for that: It accepts a bunch of individual promises and gives you back a single promise that is resolved when all of the ones you gave it are resolved, or rejected when any of them is rejected.

Does promise all wait?

Using Promise.allPromise.all waits for all fulfillments (or the first rejection).


2 Answers

You can implement that combining Promise.race and Promise.all:

function firstTrue(promises) {     const newPromises = promises.map(p => new Promise(         (resolve, reject) => p.then(v => v && resolve(true), reject)     ));     newPromises.push(Promise.all(promises).then(() => false));     return Promise.race(newPromises); } 

Test for above code:

function firstTrue(promises) {    const newPromises = promises.map(p => new Promise(      (resolve, reject) => p.then(v => v && resolve(true), reject)    ));    newPromises.push(Promise.all(promises).then(() => false));    return Promise.race(newPromises);  }    var test = values => firstTrue(    values.map((v) => new Promise((resolve) => {      setTimeout(() => resolve(v), Math.round(Math.random() * 1000));    }))  ).then((ret) => console.log(values, ret));    test([true, true, true]);  test([false, false, false]);  test([true, false, false]);  test([false, true, false]);  test([false, false, true]);
like image 164
jaboja Avatar answered Oct 14 '22 06:10

jaboja


You can create a new promise that resolves as soon as any given promise resolves to true like this:

function promiseRaceTrue(promises) {     return new Promise(function(resolve, reject) {         promises.forEach(promise =>             promise.then(val => val === true && resolve())             // TODO handle resolve with value of "false"?             // TODO handle rejection?         );         // TODO handle all resolved as "false"?     }); }  var a = await promiseRaceTrue([Promise1(), Promise2(), Promise3()]); 

It behaves similar to Promise.race but only resolves if one of the given promises resolves with the value true instead of resolving as soon as any of the given promises either resolves or rejects.

like image 31
str Avatar answered Oct 14 '22 07:10

str