I am working with a broken codebase so I am trying to touch as little as possible. In particular, right now it's using TypeScript and ES6, and I need to launch an array of promises and wait for them all to finish before I move on with the code execution, regardless of if they resolve or reject. So this is the usecase for Promise.allSettled, which is only available in ES2020.
I tried the following implementation:
const myPromiseAllSettled = (promises) => new Promise((resolve, reject) => {
const results = []
const settle = (result) => {
results.push(result)
if (results.length === promises.length) {
(results.every(value => value) ? resolve : reject)(promises)
}
}
promises.forEach(promise => {
promise
.then(() => settle(true))
.catch(() => settle(false))
})
})
but I have only seen my own code when it comes to promises, so I would like to get some feedback on my implementation. Does it do what other developers would expect it to do? Especially when it comes to the arguments passed to resolve/reject; right now I only pass the array of promises and expect the developer to run a .then(promises => promises.forEach(...)) if they are interested in following up on the individual promises.
I also don't know ideally how I would handle the types with TypeScript here, since I am not so experienced with TypeScript as well. (Writing 'any' everywhere doesn't seem cool to me.)
it should look more like this:
const myPromiseAllSettled = (promises) => {
const fulfilled = value => ({ status: "fulfilled", value });
const rejected = reason => ({ status: "rejected", reason });
return Promise.all([...promises].map(p => Promise.resolve(p).then(fulfilled, rejected)));
}
[...promises] to handle cases where promises is iterable but not an array.
Promise.resolve(p) because the passed value may be not a Promise (or thenable).
If you simply want to be notified about the success, you can do something simpler:
const success = await Promise.all(promises).then(() => true, () => false);
Edit: Didn't like the way handled promises may be an iterable but no array. Adding a version that Array#maps over iterables:
function* map(iterable, callback) {
for (const value of iterable) {
yield callback(value);
}
}
const myPromiseAllSettled = (promises) => {
const fulfilled = value => ({ status: "fulfilled", value });
const rejected = reason => ({ status: "rejected", reason });
return Promise.all(
map(
promises,
p => Promise.resolve(p).then(fulfilled, rejected)
)
);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With