I have an array with X promises and I need to return them in order of their setTimeout.
For example. if P1 has timeout set for 3000ms, and P2 resolves after 1000ms, we want to first return P2 and then P1. The code looks like this:
const P1 = new Promise((resolve) => {
setTimeout(() => resolve('R1'), 3000);
});
const P2 = new Promise((resolve) => {
setTimeout(() => resolve('R2'), 5000);
});
const P3 = new Promise((resolve) => {
setTimeout(() => resolve('R3'), 1000);
});
async function fetchInitialData(arr) {
return Promise.all(arr);
}
fetchInitialData([P1, P2, P3])
.then((data) => {
console.log('result', data);
});
In this scenario we’re returning promises but they’re not sorted by resolve time, it would return R1, R2, R3.
We want to return them by their resolve time, so in this case: R3, R1, R2.
>Solution :
In this scenario we’re returning promises but they’re not sorted by resolve time, it would return
R1,R2,R3.
Right, that’s a guarantee Promise.all provides: The array it fulfills its promise with is the fulfillment values of the input promises, in input order.
You could write your own function that instead builds the array in order of fulfillment, for instance:
async function allInFulfillmentOrder(promises) {
const result = [];
await Promise.all(
Array.from(promises, (p) => p.then((value) => result.push(value)))
);
return result;
}
There, we put the promises in the array as they’re fulfilled, returning the array when they’ve all been fulfilled (or when any of them is rejected, which will reject the promise our function returns).
Live example:
const P1 = new Promise((resolve) => {
setTimeout(() => resolve("R1"), 3000);
});
const P2 = new Promise((resolve) => {
setTimeout(() => resolve("R2"), 5000);
});
const P3 = new Promise((resolve) => {
setTimeout(() => resolve("R3"), 1000);
});
async function fetchInitialData(arr) {
return await allInFulfillmentOrder(arr);
}
fetchInitialData([P1, P2, P3]).then((data) => {
console.log("result", data);
});
async function allInFulfillmentOrder(promises) {
const result = [];
await Promise.all(
Array.from(promises, (p) => p.then((value) => result.push(value)))
);
return result;
}
The Array.from(promises, (p) => ___) is so the function supports any iterable of promises, rather than just arrays. I did that to make it consistent with Promise.all, Promise.allSettled, etc. work.