I have a Promise.allSettled which i use to resolve data in the database. I have an array of Promises which I run through the Promise.allSettled, then I only use the resolved ones. Is it possible to set a timeout inside the Promise.allSettled, so that if a promise has still not resolved the data after 5 seconds, it should return as rejected?
My code looks like this:
await Promise.allSettled(promises)
.then(result => result.forEach(d => {
if (d.status === 'fulfilled') {
data.push(d.value)
}
}));
I have a Promise.allSettled which i use to resolve data in the database. I have an array of Promises which I run through the Promise.allSettled, then I only use the resolved ones. Is it possible to set a timeout inside the Promise.allSettled, so that if a promise has still not resolved the data after 5 seconds, it should return as rejected?
My code looks like this:
await Promise.allSettled(promises)
.then(result => result.forEach(d => {
if (d.status === 'fulfilled') {
data.push(d.value)
}
}));
Share
Improve this question
edited Nov 9, 2021 at 17:00
BML91
3,2004 gold badges37 silver badges56 bronze badges
asked Dec 3, 2020 at 10:09
TheStrangerTheStranger
1,5893 gold badges25 silver badges47 bronze badges
2 Answers
Reset to default 7You could use Promise.race
on the original promise and a timeout promise that rejects, e.g.:
await Promise.allSettled(
promises.map(promise => Promise.race([promise, rejectAfterDelay(5000)])) // **
)
.then(result => result.forEach(d => {
if (d.status === 'fulfilled') {
data.push(d.value)
}
}));
...where rejectAfterDelay
is something like:
const rejectAfterDelay = ms => new Promise((_, reject) => {
setTimeout(reject, ms, new Error("timeout"));
};
Side note: You could use filter
to filter out the rejected promises:
data.push(...
await Promise.allSettled(
promises.map(promise => Promise.race([promise, rejectAfterDelay(5000)]))
).then(result => result.filter(({status}) => status === "fulfilled"))
);
...although I think I'd refactor the "allSettled
within timeout" part into a utility function, e.g.:
const fulfilledWithinTimeout = async (promises, timeout) => {
promises = Array.isArray(promises) ? promises : [...promises];
const all = await Promise.allSettled(promises.map(promise => Promise.race([promise, rejectAfterDelay(timeout)]));
return all.filter(({status}) => status === "fulfilled");
};
then
data.push(...await fulfilledWithinTimeout(promises, 5000));
With a custom Promise class it's easy Demo:
import CPromise from "c-promise2";
CPromise.allSettled([...promises])
.timeout(1000)
.catch((err) => {
console.warn(`Fail: ${err}`); // Fail: CanceledError: timeout
});
Such promises can handle cancellation:
import CPromise from "c-promise2";
CPromise.allSettled([
new CPromise((resolve, reject, { onCancel }) => {
const timer = setTimeout(resolve, 2000);
onCancel(() => {
clearTimeout(timer);
console.log("Wow! timeout cleared");
});
})
])
.timeout(1000)
.catch((err) => {
console.warn(`Fail: ${err}`);
});