Testing

JavaScript Promises: Browser Support, Methods, Limitations

JavaScript Promises support Chrome 32+, Edge 12+, Firefox 29+, Safari 8+, Opera 19+, and Samsung Internet 4+. See full JavaScript Promises browser support.

Author

Prince Dewani

May 1, 2026

JavaScript Promises are a built-in ECMA-262 object that represents the eventual completion or failure of an asynchronous operation. They support Chrome 32+, Edge 12+, Firefox 29+, Safari 8+ on macOS and iOS, Opera 19+, Samsung Internet 4+, and Android Browser 4.4.4+, while Internet Explorer never added native support.

This guide covers what JavaScript Promises are, the browsers that support them, the key features, the difference from async/await, fallback options for older browsers, and the known issues.

What are JavaScript Promises?

A Promise is a JavaScript object defined in the ECMA-262 specification that represents a value that may not be available yet. It moves through three states (pending, fulfilled, rejected) and exposes .then, .catch, and .finally handlers, plus static methods such as Promise.all, Promise.allSettled, Promise.any, and Promise.race.

Which browsers support JavaScript Promises?

Native Promise support shipped in every modern engine. Internet Explorer is the only major browser that never added a Promise constructor, and a few static methods (allSettled, any, withResolvers) arrived in later versions.

Loading browser compatibility data...

JavaScript Promises compatibility in Chrome

Chrome supports Promises from Chrome 32 on Windows, macOS, Linux, ChromeOS, and Android. Chrome 4 to 31 did not expose a global Promise constructor, so any reference to Promise threw a ReferenceError. Newer methods follow later: Promise.prototype.finally lands in Chrome 63, Promise.allSettled in Chrome 76, Promise.any in Chrome 85, and Promise.withResolvers in Chrome 119.

JavaScript Promises compatibility in Edge

Microsoft Edge supports the Promise constructor by default from Edge 12 on Windows. Promise.prototype.finally arrived in Edge 18, and Chromium-based Edge 79+ inherits Chrome's full method set, including Promise.allSettled, Promise.any, and Promise.withResolvers from Edge 119 on Windows, macOS, and Linux.

JavaScript Promises compatibility in Firefox

Firefox supports Promises from Firefox 29 on Windows, macOS, Linux, and Android. Firefox 24 to 28 had Promise behind the dom.promise.enabled flag, and Firefox 2 to 23 had no implementation. Promise.prototype.finally lands in Firefox 58, Promise.allSettled in Firefox 71, Promise.any in Firefox 79, and Promise.withResolvers in Firefox 121.

JavaScript Promises compatibility in Safari

Safari supports Promises from Safari 8 on macOS Yosemite and from Safari 8 on iOS 8. Safari 3.1 to 7.1 on macOS and Safari 3.2 to 7.1 on iOS did not expose a Promise constructor. Promise.prototype.finally ships in Safari 11.1, Promise.allSettled in Safari 13, Promise.any in Safari 14, and Promise.withResolvers in Safari 17.4.

JavaScript Promises compatibility in Opera

Opera supports Promises from Opera 19 on Windows, macOS, and Linux through the Chromium 32 base. Opera 9 to 18 on desktop did not implement Promise. Promise.prototype.finally lands in Opera 50, Promise.allSettled in Opera 63, Promise.any in Opera 71, and Promise.withResolvers in Opera 105.

JavaScript Promises compatibility in Samsung Internet

Samsung Internet supports Promises from Samsung Internet 4 on Galaxy phones and tablets running Android. Promise.prototype.finally ships in Samsung Internet 8, Promise.allSettled in Samsung Internet 12, and Promise.any in Samsung Internet 14. Modern Samsung Internet builds align with the underlying Chromium release.

JavaScript Promises compatibility in Android Browser

The legacy stock Android Browser supports Promises from Android Browser 4.4.4 on Android KitKat. Android Browser 2.1 to 4.4 did not expose Promise. Modern Android Browser builds inherit Chrome's full Promise method set, so Promise.allSettled, Promise.any, and Promise.withResolvers all run on any current Android phone with Chrome for Android or a Chromium-based shell.

JavaScript Promises compatibility in Internet Explorer

Internet Explorer never added native Promise support. IE 5.5 through IE 11 throw a ReferenceError when any script references the global Promise constructor. Microsoft has retired Internet Explorer, so use Edge, Chrome, or Firefox, or load a Promise polyfill such as es6-promise or core-js before any script that uses Promise.

Note

Note: Promise method support varies across older Safari, mobile browsers, and Internet Explorer. Test it on real browsers and OS with TestMu AI. Try TestMu AI free!

What are the key features of JavaScript Promises?

Promises ship a small set of methods and guarantees that replace nested callback code with a flat, composable chain. Each feature below is part of the ECMA-262 specification and runs natively in every modern browser.

  • Three states: A Promise starts as pending, transitions exactly once to fulfilled with a value or rejected with a reason, and stays in its final state forever. Handlers attached after settling fire on the next microtask.
  • Chainable .then, .catch, .finally: Each handler returns a new Promise, so .then(a).then(b).catch(c) reads top to bottom. .finally runs regardless of outcome and is the right place for cleanup such as hiding a loading spinner.
  • Promise.all for parallel work: Promise.all([a, b, c]) fulfills with an array of values when every input fulfills, or rejects on the first rejection. Use it to fan out independent network calls and resume only when all of them finish.
  • Promise.allSettled for partial failure: Promise.allSettled never rejects. It resolves with an array of {status, value} or {status, reason} objects, which is the right tool when one failed call should not abort the rest.
  • Promise.any for first success: Promise.any fulfills with the first input that fulfills. If every input rejects, it rejects with an AggregateError. Use it for redundant calls to mirrored endpoints where the fastest success wins.
  • Promise.race for first settled: Promise.race settles with whichever input settles first, fulfilled or rejected. It is the standard primitive for adding a timeout to a slow operation.
  • Promise.withResolvers for deferred patterns: Promise.withResolvers returns {promise, resolve, reject}, which removes the boilerplate of capturing resolve and reject from inside a Promise constructor when an external event must settle the Promise.
  • Microtask scheduling: Every Promise callback runs on the microtask queue, which drains before the next render and before any setTimeout 0 callback. This makes Promise resolution faster than queueMicrotask wrappers around setTimeout.

What is the difference between JavaScript Promises and async/await?

Async/await is syntax sugar over Promises, so the two work together rather than competing. The table below shows how the syntax, control flow, error handling, and browser reach differ in practice.

DimensionPromisesAsync/await
Syntax styleChained .then() and .catch() callbacksTop-to-bottom code with await
Return typeAlways a Promise (constructed explicitly)Always a Promise (wrapped automatically)
Error handling.catch() handler at the end of the chaintry/catch around awaits
Conditional flowNested .then() callbacks or helper functionsStandard if/else and loops with await
ConcurrencyPromise.all, Promise.race, Promise.allSettled directlyawait Promise.all for parallel work
Browser supportChrome 32+, Edge 12+, Firefox 29+, Safari 8+Chrome 55+, Edge 15+, Firefox 52+, Safari 11+
Best fitLibrary APIs, low-level control, IE-compatible codeSequential awaits, readable error paths, modern code
...

How do you use JavaScript Promises in older browsers?

Load a Promise polyfill before any script that calls Promise. The polyfill installs a global Promise constructor that matches the ECMA-262 specification, so the same Promise chain runs on Internet Explorer 11 and on every modern engine.

  • Pick a polyfill: Use es6-promise, core-js/features/promise, or Bluebird. es6-promise is the smallest, core-js covers every newer Promise method, and Bluebird adds extras such as Promise.map and cancellation.
  • Install through npm: Run npm install es6-promise (or the package of your choice) and add it as a runtime dependency, not a devDependency, so the polyfill ships with your bundle.
  • Import the auto-shim entry: Add import "es6-promise/auto" at the very top of your entry file. The auto entry assigns window.Promise only if the global is missing, so modern browsers keep their native implementation.
  • Cover newer methods: Add core-js/features/promise/all-settled, core-js/features/promise/any, and core-js/features/promise/with-resolvers if your code uses any of those static methods.
  • Confirm in the target browser: Open your compiled bundle in Internet Explorer 11 or your oldest target, paste the snippet below into the DevTools console, and check that the user object prints without a ReferenceError.
function loadUser(id) {
    return fetch("/api/users/" + id)
        .then(function (response) {
            if (!response.ok) {
                throw new Error("User fetch failed: " + response.status);
            }
            return response.json();
        });
}

loadUser(42)
    .then(function (user) {
        console.log("User loaded:", user.name);
    })
    .catch(function (error) {
        console.error("Could not load user:", error);
    });

If the console reports "Promise is not defined", the polyfill import is missing or imported after the first Promise call. Move the polyfill import to the very first line of the entry file and rebuild.

...

What are the known issues with JavaScript Promises?

Promises are stable, but a handful of behaviors trip up developers and cause cross-browser bugs. Most of them come from the gap between the spec and how each engine schedules microtasks or surfaces unhandled rejections.

  • Internet Explorer has no Promise constructor: IE 5.5 through 11 throw a ReferenceError when any script references Promise. Any bundle that ships raw Promise code breaks IE outright, so load es6-promise or core-js before deployment.
  • Unhandled rejections crash on some hosts: A rejected Promise without a .catch fires an unhandledrejection event. Modern Node treats it as a crash by default, and old Safari logged it silently, so always attach .catch on the outermost chain.
  • Promises are not cancellable: The ECMA-262 specification has no cancel method. To cancel an in-flight fetch or animation, pair the Promise with an AbortController and reject on signal.aborted.
  • Returning the wrong value breaks chaining: Forgetting to return inside a .then handler sends undefined to the next link in the chain. ESLint rule promise/always-return catches this at lint time.
  • .then(onFulfilled, onRejected) hides errors: The onRejected argument only handles rejections from the previous Promise, not errors thrown inside onFulfilled. Use a separate .catch at the end of the chain instead.
  • Promise.all rejects on first failure: One failed input rejects the whole aggregate and discards every other result. Switch to Promise.allSettled when partial failure is acceptable.
  • Microtask starvation: A long chain of synchronous .then callbacks can starve rendering because microtasks drain before the next paint. Break long chains with await yield or queueMicrotask checkpoints.
  • Method support varies by version: Promise.allSettled, Promise.any, and Promise.withResolvers ship in different browser versions than the constructor itself, so feature-detect each method before calling it on older targets.

In my experience, the trickiest production failure is a missing .catch on a top-level chain that runs only on a rare error path. The browser quietly fires unhandledrejection in development, but on real devices the same chain crashes a Service Worker install or aborts a Stripe checkout. Always anchor every Promise chain with a final .catch and log to your error reporter.

Citations

All JavaScript Promise version numbers and platform notes in this guide come from these primary sources:

Author

Prince Dewani is a Community Contributor at TestMu AI, where he manages content strategies around software testing, QA, and test automation. He is certified in Selenium, Cypress, Playwright, Appium, Automation Testing, and KaneAI. Prince has also presented academic research at the international conference PBCON-01. He further specializes in on-page SEO, bridging marketing with core testing technologies. On LinkedIn, he is followed by 4,300+ QA engineers, developers, DevOps experts, tech leaders, and AI-focused practitioners in the global testing community.

Open in ChatGPT Icon

Open in ChatGPT

Open in Claude Icon

Open in Claude

Open in Perplexity Icon

Open in Perplexity

Open in Grok Icon

Open in Grok

Open in Gemini AI Icon

Open in Gemini AI

Copied to Clipboard!
...

3000+ Browsers. One Platform.

See exactly how your site performs everywhere.

Try it free
...

Write Tests in Plain English with KaneAI

Create, debug, and evolve tests using natural language.

Try for free

Frequently asked questions

Did you find this page helpful?

More Related Hubs

TestMu AI forEnterprise

Get access to solutions built on Enterprise
grade security, privacy, & compliance

  • Advanced access controls
  • Advanced data retention rules
  • Advanced Local Testing
  • Premium Support options
  • Early access to beta features
  • Private Slack Channel
  • Unlimited Manual Accessibility DevTools Tests