promise-polyfill

A lightweight, spec-compliant ES6 Promise polyfill for browsers and Node.js environments that lack native Promise support.

Library
npm
v8.3.0
2,142stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
50/100Fair
Development Activity0
Maintenance20
Community80
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
65/100Good
Architecture72
Code Quality78
Innovation65
Learning Curve45

promise-polyfill provides a drop-in implementation of the ES6 Promise API for older browsers (IE8+) and runtimes that predate native Promise support. It closely follows the Promises/A+ specification and is verified against the official promises-aplus-tests compliance suite, so it behaves identically to the native Promise object it stands in for.

The library ships two entry points: a global-installing polyfill that patches window.Promise (or adds missing static methods like finally, allSettled, and any to an existing native Promise), and a ponyfill export for library authors who don’t want to touch global state. At well under 1kb gzipped, it’s small enough to include unconditionally in a build targeting legacy browsers.

What You Get

  • A full Promise implementation: constructor, then/catch/finally, and the static helpers all/race/resolve/reject/any/allSettled
  • A global-installing entry point (promise-polyfill/src/polyfill) that sets window.Promise/global.Promise only when native support is absent
  • A ponyfill entry point (default export of the package) for code that shouldn’t mutate global state
  • Prebuilt UMD bundles (dist/polyfill.js, dist/polyfill.min.js) usable directly via a <script> tag or CDN, alongside CJS/ESM builds for bundlers
  • Configurable internals — override the async scheduler via Promise._immediateFn or silence/replace unhandled-rejection warnings via Promise._unhandledRejectionFn

Common Use Cases

  • Shimming Promise support into a website that must run on legacy browsers like IE8-IE11
  • Adding missing Promise statics (finally, allSettled, any) to an otherwise-native Promise in older Node.js or partially-supporting engines
  • Using Promises inside a shared library without polluting the global namespace, via the ponyfill import
  • Loading a zero-dependency Promise shim straight from a CDN for a static HTML page with no build step

Under The Hood

Architecture src/index.js defines the core Promise constructor plus then/catch/finally/all/race/resolve/reject, all funneled through a small internal state machine (handle/resolve/reject/finale functions operating on private _state/_value/_deferreds properties) implemented with plain closures rather than classes — no build-time codegen, just five small composable files (index.js, polyfill.js, finally.js, allSettled.js, any.js). index.js exports the constructor as a ponyfill, while polyfill.js is the side-effecting entry that assigns it to the detected global object only when a native Promise is absent, or patches finally/allSettled/any onto an existing native Promise when missing. Because every static and instance method routes through the same doResolve/handle state machine, a change to that core would require re-verifying all of them.

Tech Stack Written in plain ES5-targeted JavaScript with JSDoc type annotations checked via tsc --checkJS and Google Closure Compiler advanced-mode checks for dead-code elimination; no runtime dependencies at all. Built with Rollup into CJS (lib/) and UMD (dist/) bundles; ESLint plus Prettier enforce style, with Husky and lint-staged gating commits. Published to both npm and Bower, and embeddable directly from the jsdelivr CDN as a UMD script.

Code Quality Two parallel test suites cover the implementation: a Mocha unit-test file with dozens of cases covering constructor errors, then/catch/finally chaining, and edge cases across all/race/any/allSettled and unhandled-rejection warnings, plus a full run of the official promises-aplus-tests conformance suite executed through Karma in a real browser — meaning correctness is checked against the canonical A+ specification tests, not just author-written cases. Error handling is deliberate throughout doResolve (try/catch around user resolver functions guarded by a done flag against double-settlement), and naming is terse but consistent with the classic open-source promise implementation this project descends from.

API Design Its main differentiator versus reaching for another polyfill is the dual entry-point design: import the polyfill path for a zero-config global shim ideal for app bundlers targeting legacy browsers, or import the default export as a ponyfill that never touches the global object — recommended for library authors. The public surface intentionally mirrors the native Promise API one-to-one, so swapping between native and polyfilled Promise is a single import-line change, and two documented escape hatches (Promise._immediateFn, Promise._unhandledRejectionFn) let consumers override scheduling or rejection-warning behavior without forking the library.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search