Promise.prototype.finally()
The finally()
method of a Promise
object schedules a function to be called when the promise is settled (either fulfilled or rejected). It immediately returns an equivalent Promise
object, allowing you to chain calls to other promise methods.
This lets you avoid duplicating code in both the promise's Promise.prototype.then
and Promise.prototype.catch
handlers.
Syntax
finally(onFinally)
finally(() => {
// Code that will run after promise is settled (fulfilled or rejected)
})
Parameters
onFinally
- : A
Function
called when thePromise
is settled. This handler receives no parameters.
- : A
Return value
Returns an equivalent Promise
. If the handler throws an error or returns a rejected promise, the promise returned by finally()
will be rejected with that value instead. Otherwise, the return value of the handler does not affect the state of the original promise.
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.
- The
onFinally
callback does 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 is usually transparent and does not change the eventual state of the original promise. So for example:- Unlike
Promise.resolve(2).then(() => 77, () => {})
, which returns a promise eventually fulfilled with the value77
,Promise.resolve(2).finally(() => 77)
returns a promise eventually fulfilled with the value2
. - Similarly, unlike
Promise.reject(3).then(() => {}, () => 88)
, which returns a promise eventually fulfilled with the value88
,Promise.reject(3).finally(() => 88)
returns a promise eventually rejected with the reason3
.
- Unlike
Note: A
throw
(or returning a rejected promise) in thefinally
callback still rejects the returned promise. For example, bothPromise.reject(3).finally(() => { throw 99; })
andPromise.reject(3).finally(() => Promise.reject(99))
reject the returned promise with the reason99
.
Like Promise.prototype.catch()
, finally()
internally calls the then
method on the object upon which it was called. If onFinally
is not a function, then()
is called with onFinally
as both arguments — which, for Promise.prototype.then()
, means that no useful handler is attached. Otherwise, then()
is called with two internally created functions, which behave like the following:
Warning: This is only for demonstration purposes and is not a polyfill.
promise.then(
(value) => Promise.resolve(onFinally()).then(() => value),
(reason) =>
Promise.resolve(onFinally()).then(() => {
throw reason;
}),
);
Because finally()
calls then()
, it supports subclassing. Moreover, notice the Promise.resolve()
call above — in reality, onFinally()
's return value is resolved using the same algorithm as Promise.resolve()
, but the actual constructor used to construct the resolved promise will be the subclass. finally()
gets this constructor through promise.constructor[Symbol.species]
.