Polyfilling Promise.allSettled with CoreJS for Legacy Environments
Learn how to add a reliable Promise.allSettled polyfill using core-js, see a concrete example, and understand the trade-offs before adding it to your bundle.
16 Jul 2026, 05:30 UTC

The problem: missing Promise.allSettled in older runtimes
Modern JavaScript provides Promise.allSettled as a convenient way to wait for a collection of promises, regardless of whether each resolves or rejects. However, environments such as Internet Explorer 11, older versions of Safari, or Node.js releases prior to v12 do not expose this method natively. When your code relies on Promise.allSettled you either need to avoid the feature altogether or ship a polyfill that patches the global Promise object.
Thesis: a single-line CoreJS import gives a drop-in, spec-compliant polyfill
CoreJS version 3.x ships a stable, standalone polyfill for Promise.allSettled under the path core-js/stable/promise/all-settled. Importing this module once patches Promise.allSettled onto the global Promise constructor, after which the method behaves exactly like the native implementation—returning an array of objects with status, value (for fulfilled promises) or reason (for rejected ones). The polyfill respects edge cases such as non-thenable values and throws the same TypeError for invalid arguments.
Worked example: adding and using the polyfill
Assume you are building a library that must run in Node.js 10 and also in browsers that lack native support. The steps below show where to run the commands, what permissions are needed, and what to check.
- Install CoreJS (run in your project root, requires npm or yarn write access):
npm install core-js@3 # or: yarn add core-js@3 - Import the polyfill early in your entry point (e.g.,
src/index.js) before any code that callsPromise.allSettled:// src/index.js import 'core-js/stable/promise/all-settled'; // patches global Promise async function run() { const p1 = Promise.resolve('ok'); const p2 = Promise.reject(new Error('fail')); const results = await Promise.allSettled([p1, p2]); console.log(results); } run(); - Run the code (Node.js 10 example):
Expected output (structure only, not exact timestamps):node src/index.js[ { status: 'fulfilled', value: 'ok' }, { status: 'rejected', reason: Error: fail } ] - Verify the patch (optional, run in a console):
// After the import, check that the method exists and carries the CoreJS marker console.log(typeof Promise.allSettled); // "function" console.log(Promise.allSettled.toString().includes('core-js')); // true if patched
No special privileges are required beyond normal package installation and script execution rights.
Trade-offs and limitations
- Bundle size: Adding
core-js/stable/promise/all-settledcontributes roughly 1-2 KB (gzipped) to your JavaScript bundle. If you already use CoreJS for other features, the incremental cost is smaller; otherwise, consider whether the feature is essential for your target audience. - Duplicate polyfills: Importing the same polyfill more than once (e.g., via another library that also patches
Promise.allSettled) can cause the method to be redefined, potentially leading to unexpected behavior or unnecessary work. Audit your dependencies to ensure only one source applies the patch. - Runtime overhead: The polyfill wraps the native method when present, but in environments lacking the native implementation it adds a small function call overhead. This is typically negligible compared to the cost of the promises themselves.
Actionable closing
If you need to support runtimes that do not ship Promise.allSettled natively, the CoreJS stable polyfill offers a simple, spec-compliant solution with minimal code changes. Add the import early, verify the patch in a low-version environment, and keep an eye on bundle size to avoid unnecessary bloat. When your target baseline moves forward and native support becomes universal, you can safely remove the import and let the engine's built-in method take over.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.