Get to know MDN better
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
The then() method of Promise instances takes up to two arguments: callback functions for the fulfilled and rejected cases of the Promise. It stores the callbacks within the promise it is called on and immediately returns another Promise object, allowing you to chain calls to other promise methods.
A function to asynchronously execute when this promise becomes fulfilled. Its return value becomes the fulfillment value of the promise returned by then(). The function is called with the following arguments:
valueThe value that the promise was fulfilled with.
If it is not a function, it is internally replaced with an identity function ((x) => x) which simply passes the fulfillment value forward.
onRejected OptionalA function to asynchronously execute when this promise becomes rejected. Its return value becomes the fulfillment value of the promise returned by then(). The function is called with the following arguments:
reasonThe value that the promise was rejected with.
If it is not a function, it is internally replaced with a thrower function ((x) => { throw x; }) which throws the rejection reason it received.
Returns a new Promise immediately. This returned promise is always pending when returned, regardless of the current promise's status.
One of the onFulfilled and onRejected handlers will be executed to handle the current promise's fulfillment or rejection. The call always happens asynchronously, even when the current promise is already settled. The behavior of the promise returned by then() (referred to as p in the following list) depends on the handler's execution result, following a specific set of rules. If the handler function:
The then() method schedules callback functions for the eventual completion of a Promise — either fulfillment or rejection. It is the primitive method of promises: the thenable protocol expects all promise-like objects to expose a then() method, and the catch() and finally() methods both work by invoking the object's then() method.
For more information about the onRejected handler, see the catch() reference.
then() returns a new promise object but mutates the promise object it's called on, appending the handlers to an internal list. Therefore the handler is retained by the original promise and its lifetime is at least as long as the original promise's lifetime. For example, the following example will eventually run out of memory even though the returned promise is not retained:
If you call the then() method twice on the same promise object (instead of chaining), then this promise object will have two pairs of settlement handlers. All handlers attached to the same promise object are always called in the order they were added. Moreover, the two promises returned by each call of then() start separate chains and do not wait for each other's settlement.
Thenable objects that arise along the then() chain are always resolved — the onFulfilled handler never receives a thenable object, and any thenable returned by either handler are always resolved before being passed to the next handler. This is because when constructing the new promise, the resolve and reject functions passed by the executor are saved, and when the current promise settles, the respective function will be called with the fulfillment value or rejection reason. The resolving logic comes from the resolve function passed by the Promise() constructor.
then() supports subclassing, which means it can be called on instances of subclasses of Promise, and the result will be a promise of the subclass type. You can customize the type of the return value through the [Symbol.species] property.
The then method returns a new Promise, which allows for method chaining.
If the function passed as handler to then returns a Promise, an equivalent Promise will be exposed to the subsequent then in the method chain. The below snippet simulates asynchronous code with the setTimeout function.
The value returned from then() is resolved in the same way as Promise.resolve(). This means thenable objects are supported, and if the return value is not a promise, it's implicitly wrapped in a Promise and then resolved.
A then call returns a promise that eventually rejects if the function throws an error or returns a rejected Promise.
In practice, it is often desirable to catch() rejected promises rather than then()'s two-case syntax, as demonstrated below.
In all other cases, the returned promise eventually fulfills. In the following example, the first then() returns 42 wrapped in a fulfilled Promise, even though the previous Promise in the chain was rejected.
If onFulfilled returns a promise, the return value of then will be fulfilled/rejected based on the eventual state of that promise.
You can use chaining to implement one function with a Promise-based API on top of another such function.
The following is an example to demonstrate the asynchronicity of the then method.
| ECMAScript® 2027 Language Specification # sec-promise.prototype.then |
Enable JavaScript to view this browser compatibility table.
This page was last modified on Jul 15, 2025 by MDN contributors.
Your blueprint for a better internet.
Visit Mozilla Corporation’s not-for-profit parent, the Mozilla Foundation.
Portions of this content are ©1998–2026 by individual mozilla.org contributors. Content available under a Creative Commons license.