Home > Software design >  How do asynchronous OR (||) / AND (&&) tests work?
How do asynchronous OR (||) / AND (&&) tests work?

Time:01-10

I know the promise library Promise. methods provides simple ways to resolve AND(&&) / OR(||) tests, but I would like to understand how they work. Could someone help me understand better?

merely illustrative:

const test = (time, response_value) => new Promise((resolve, reject) => {
  setTimeout(resolve, time, response_value);
});

(async () => {
    //returns the faster (but not)
    console.log(await (test(Math.random()*500, 'one') || test(Math.random()*500, 'two') || test(Math.random()*500, 'three')) );
    
    //returns two if the first returns true (but not)
    console.log(await (test(Math.random()*500, parseInt(Math.random()*2)) && test(Math.random()*500, 'two')) ); 
})()

CodePudding user response:

Simplifying some of the code, you're asking about these cases:

await (promiseA || promiseB || promiseC)
// vs
await (promiseA && promiseB)

Both of these are almost certainly not what you want to do. The first one will start by evaluating promiseA || promiseB || promiseC. Promises are objects, and objects are truthy, so the first part of the || is enough to satisfy it. So this calculation results in promiseA and the code ends up just doing await promiseA with some side effects. Only promiseA will be awaited, and only it will contribute to the log statement.

The second one starts by evaluating promiseA && promiseB. Promise objects are again truthy, and the && operator means this calculation will result in promiseB. So you end up doing await promiseB.

What you very likely meant to do is to use || and && on the values inside the promises, not the promises themselves. To do that, you will need to await all of the promises, and then do a comparison with the resulting values. So for example:

const a = await promiseA;
const b = await promiseB;
const c = await promiseC;
console.log(a || b || c);

Or to do it in parallel:

const [a, b, c] = await Promise.all([promiseA, promiseB, promiseC]);
console.log(a || b || c);

CodePudding user response:

If you want to test stuff you probably shouldn't use random values as this won't give you reproducible results that are easy to understand.

As the other answer already said, Promises are objects so promiseA || promiseB and promiseA && promiseB work on those objects and not on the values they possibly resolve to.

The await in await (promiseA || promiseB) and await (promiseA && promiseB) is applied on the result of the evaluation of promiseA || promiseB (which is promiseA) or of promiseA && promiseB (which is always promiseB)

If you want to work on the values the Promises resolve to you need to move the await to the Promises directly:

async function run() {
  console.log(await Promise.resolve(0) || await Promise.resolve(1))
  console.log(await Promise.resolve(0) && await Promise.resolve(1))
}

run();

The comment //returns the faster (but not) indicate that you look for Promise.race():

const test = (time, response_value) => new Promise((resolve, reject) => {
  setTimeout(resolve, time, response_value);
});

(async() => {
  console.log(await Promise.race(
    [
      test(300, 'one'),
      test(200, 'two'),
      test(100, 'three')
    ]
  ));
})()

The comment //returns two if the first returns true indicates you want: await Promise.resolve(true) && await Promise.resolve('two')

async function run() {
  console.log(await Promise.resolve(true) && await Promise.resolve('two'))
  console.log(await Promise.resolve(false) && await Promise.resolve('two'))
}

run();

  •  Tags:  
  • Related