@reworded question
I know the Promise.
methods provide simple ways to solve AND (&& => Promise.all
) , OR (|| => Promise.any
) or Promise.race
for tests when you want the first promise that return a result, but I'd like to understand the construction logic and if it is possible to take advantage of asynchronous objects to do these operations in asynchronous functions (something like the assumption below)
Can someone give me a light?
const test = (time, response_value) => new Promise((resolve, reject) => {
setTimeout(resolve, time, response_value);
});
(async () => {
//returns the first result that returns true
console.log( await (test(Math.random()*500, 'one') || test(Math.random()*500, 'two')) );
//returns the last promise if the first returns true
console.log( await (test(Math.random()*500, parseInt(Math.random()*2)) && test(Math.random()*500, 'two')) );
//returns the fastest result
//???
})();
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);
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();