Promise.allSettled in babel ES6 implementation
Solution 1
Alternatively, which is a good algorithm for me to try to implement?
- create a new promise with an executor function
- use a counter/result array in the scope of the executor
- register a then() callback with each parent promise saving the results in the array
- resolve/reject promise from step 1 when counter indicates that all parent promises are done
Solution 2
2019 Answer
There was a proposal to add this function to the ECMAScript standard, and it has been accepted! Check out the Promise.allSettled
docs for details.
Original Answer
If you take a look at the implementation of q.allSettled you'll see it's actually quite simple to implement. Here's how you might implement it using ES6 Promises:
function allSettled(promises) {
let wrappedPromises = promises.map(p => Promise.resolve(p)
.then(
val => ({ status: 'fulfilled', value: val }),
err => ({ status: 'rejected', reason: err })));
return Promise.all(wrappedPromises);
}
Solution 3
2020 answer:
What the other answers are trying to do is to implement Promise.allSettled
themselves. This was already done by the core-js project.
What you need to do is to make babel polyfill Promise.allSettled
for you via core-js. The way you configure it to do so is through @babel/preset-env
like so:
presets: [
['@babel/preset-env', {
useBuiltIns: 'usage',
corejs: {version: 3, proposals: true},
}],
],
In your build artifact this will add a call to require("core-js/modules/esnext.promise.all-settled")
which monkeypatches the .allSettled
function to the promises API.
Solution 4
const allSettled = promises =>
Promise.all(promises.map(promise => promise
.then(value => ({ state: 'fulfilled', value }))
.catch(reason => ({ state: 'rejected', reason }))
));
Or if you insist on polyfilling it:
if (Promise && !Promise.allSettled) {
Promise.allSettled = function (promises) {
return Promise.all(promises.map(function (promise) {
return promise.then(function (value) {
return { state: 'fulfilled', value: value };
}).catch(function (reason) {
return { state: 'rejected', reason: reason };
});
}));
};
}
Taken from here
Solution 5
Here's my attempt at something similar, I have Newsletter service and in my case I wanted my allSettled promise to resolve with an array of all the results (rejections and resolutions), IN ORDER, once all the email_promises are settled (all the emails had gone out):
Newsletter.prototype.allSettled = function(email_promises) {
var allSettledPromise = new Promise(function(resolve, reject) {
// Keep Count
var counter = email_promises.length;
// Keep Individual Results in Order
var settlements = [];
settlements[counter - 1] = undefined;
function checkResolve() {
counter--;
if (counter == 0) {
resolve(settlements);
}
}
function recordResolution(index, data) {
settlements[index] = {
success: true,
data: data
};
checkResolve();
}
function recordRejection(index, error) {
settlements[index] = {
success: false,
error: error
};
checkResolve();
}
// Attach to all promises in array
email_promises.forEach(function(email_promise, index) {
email_promise.then(recordResolution.bind(null, index))
.catch(recordRejection.bind(null, index));
});
});
return allSettledPromise;
}
Comments
-
Zlatko almost 2 years
I'm using
babel
to transpile my[email protected]
code and I'm stuck with promises.I need
allSettled
-type functionality that I could use inq
andbluebird
orangular.$q
for example.On babel's core-js
Promise
, there is noallSettled
method.Currently I'm using
q.allSettled
as a workaround:import { allSettled } from 'q';
Is there something like that in babel polyfill? Alternatively, which is a good algorithm for me to try to implement?