Promise Method Polyfills
Recreate Promise.all, Promise.allSettled, Promise.any, and Promise.race to understand JavaScript async settlement behavior.
Custom Implementations of JavaScript Promise Methods
Static Promise methods differ by the settlement condition they wait for. These custom implementations show how Promise.all() preserves result order,
Promise.allSettled() collects every outcome, Promise.any() resolves on the first fulfillment, and Promise.race() settles on the first completion.
Promise.all
The Promise.all() static method takes an iterable of promises and returns a single Promise that:
- fulfills when all input promises have fulfilled, returning an array of results in the original order
- rejects immediately if any promise rejects, with the first rejection reason
function myPromiseAll(promises) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promises)) {
return reject(new TypeError("Argument must be an array"));
}
const results = [];
let completedPromises = 0;
for (let index = 0; index < promises.length; index++) {
Promise.resolve(promises[index])
.then((value) => {
results[index] = value;
console.log(value);
completedPromises += 1;
if (completedPromises === promises.length) {
resolve(results);
}
})
.catch(reject);
}
if (promises.length === 0) {
resolve([]);
}
});
}
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 3000, "first");
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, "second");
});
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 5000, "third");
});
myPromiseAll([promise1, promise2, promise3]).then((values) => {
console.log(values);
});
// second
// first
// third
// [ 'first', 'second', 'third' ]Promise.allSettled
The Promise.allSettled()
method returns a promise that resolves after all promises in the input iterable have settled, regardless of whether they were fulfilled or rejected.
Each result is an object with a status of either "fulfilled" or "rejected" and contains either the value or the reason.
const rejectHandler = (reason) => ({ status: "rejected", reason });
const resolveHandler = (value) => ({ status: "fulfilled", value });
Promise.customAllSettled = function (promises) {
const convertedPromises = promises.map((p) =>
Promise.resolve(p).then(resolveHandler, rejectHandler),
);
return Promise.all(convertedPromises);
};
Promise.customAllSettled([
new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
new Promise((resolve, reject) =>
setTimeout(() => reject(new Error("Whoops!")), 2000),
),
new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000)),
])
.then(console.info)
.catch(console.error);
// [
// { status: 'fulfilled', value: 1 },
// {
// status: 'rejected',
// reason: Error: Whoops!...
// },
// { status: 'fulfilled', value: 3 }
// ]Promise.any
The Promise.any()
method returns a promise that fulfills as soon as any of the input promises is fulfilled.
If all promises reject, it rejects with an AggregateError
containing all rejection reasons.
Promise.customAny = function (promises) {
return new Promise((resolve, reject) => {
const errors = [];
let remaining = promises.length;
if (remaining === 0) {
return reject(new AggregateError([], "All promises were rejected"));
}
promises.forEach((promise, index) => {
Promise.resolve(promise)
.then(resolve)
.catch((error) => {
errors[index] = error;
remaining -= 1;
if (remaining === 0) {
reject(new AggregateError(errors, "All promises were rejected"));
}
});
});
});
};
const promise1 = Promise.reject(0);
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, "quick"));
const promise3 = new Promise((resolve) => setTimeout(resolve, 500, "slow"));
const promises = [promise1, promise2, promise3];
Promise.customAny(promises).then((value) => console.log(value)); // quickPromise.race
The Promise.race()
method returns a promise that settles as soon as the first input promise settles — whether it fulfills or rejects.
This makes it useful when you're interested only in the fastest outcome, regardless of its result.
Promise.customRace = function (promises) {
return new Promise((resolve, reject) => {
for (const promise of promises) {
Promise.resolve(promise).then(resolve, reject);
}
});
};
Promise.customRace([
new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
new Promise((resolve, reject) =>
setTimeout(() => reject(new Error("Whoops!")), 2000),
),
new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000)),
]).then(console.log); // 1JavaScript Map, Set, and Grouping Methods
Learn Map, Set, Object.groupBy, and Map.groupBy with examples for keyed collections, unique values, set operations, and grouped data.
Common JavaScript Utility Functions
Learn practical JavaScript utilities like clsx, deepClone, retry, topological sort, filterMap, innerJoin, and reducer patterns.