Promise.prototype.finally()

The finally() method of a Promise schedules a function, the callback function, to be called when the promise is settled. Like then() and catch(), it immediately returns an equivalent Promise object, allowing you to chain calls to another promise method, an operation called composition.

This lets you avoid duplicating code in both the promise's then() and catch() handlers.

Try it

Syntax

promise.finally(onFinally);

promise.finally(() => {
   // Code that will run after promise is settled (fulfilled or rejected)
});

Parameters

onFinally

A Function called when the Promise is settled.

Return value

Returns an equivalent Promise with its finally handler set to the specified function. If the handler throws an error, that promise will be rejected with that value instead.

Description

The finally() method can be useful if you want to do some processing or cleanup once the promise is settled, regardless of its outcome.

The finally() method is very similar to calling .then(onFinally, onFinally), however, there are a couple of differences:

  • When creating a function inline, you can pass it once, instead of being forced to either declare it twice, or create a variable for it
  • A finally callback will not receive any argument. This use case is for precisely when you do not care about the rejection reason, or the fulfillment value, and so there's no need to provide it.
  • A finally call will usually chain through an equivalent to the original promise.
    So for example:
    • Unlike Promise.resolve(2).then(() => 77, () => {}) (which will return a resolved promise with the result 77), Promise.resolve(2).finally(() => {}) will return a new resolved promise with the result 2.
    • Similarly, unlike Promise.reject(3).then(() => {}, () => 88) (which will return a rejected promise with the reason 88), Promise.reject(3).finally(() => 88) will return a rejected promise with the reason 3.
    • But, either Promise.reject(3).finally(() => throw 99) or Promise.reject(3).finally(() => Promise.reject(99)) will reject the returned promise with the reason 99.

Note: A throw (or returning a rejected promise) in the finally callback will reject the returned promise, with the reason specified when throwing, as shown in the last example.

Examples

Using finally

let isLoading = true;

fetch(myRequest).then(function(response) {
    const contentType = response.headers.get("content-type");
    if(contentType && contentType.includes("application/json")) {
      return response.json();
    }
    throw new TypeError("Oops, we haven't got JSON!");
  })
  .then(function(json) { /* process your JSON further */ })
  .catch(function(error) { console.error(error); /* this line can also throw, e.g. when console = {} */ })
  .finally(function() { isLoading = false; });

Specifications

Specification
ECMAScript Language Specification
# sec-promise.prototype.finally

Browser compatibility

BCD tables only load in the browser

See also