Promise.prototype.finally()
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since October 2018.
Promise
实例的 finally()
方法安排一个函数在承诺完成(履行或拒绝)时调用。它立即返回另一个 Promise
对象,允许你对其他承诺方法进行 chain 调用。
¥The finally()
method of Promise
instances schedules a function to be called when the promise is settled (either fulfilled or rejected). It immediately returns another Promise
object, allowing you to chain calls to other promise methods.
这可以让你避免在 Promise 的 then()
和 catch()
处理程序中重复代码。
¥This lets you avoid duplicating code in both the promise's then()
and catch()
handlers.
Try it
语法
参数
返回值
¥Return value
立即返回新的 Promise
。无论当前 Promise 的状态如何,该新 Promise 在返回时始终处于待处理状态。如果 onFinally
抛出错误或返回被拒绝的 Promise,则新的 Promise 将以该值拒绝。否则,新的 Promise 将以与当前 Promise 相同的状态进行结算。
¥Returns a new Promise
immediately. This new promise is always pending when returned, regardless of the current promise's status. If onFinally
throws an error or returns a rejected promise, the new promise will reject with that value. Otherwise, the new promise will settle with the same state as the current promise.
描述
¥Description
如果你想要在承诺解决后进行一些处理或清理(无论其结果如何),则 finally()
方法可能很有用。
¥The finally()
method can be useful if you want to do some processing or cleanup once the promise is settled, regardless of its outcome.
finally()
方法与调用 then(onFinally, onFinally)
非常相似。但是,存在一些差异:
¥The finally()
method is very similar to calling then(onFinally, onFinally)
. However, there are a couple of differences:
- 创建内联函数时,你可以传递一次,而不是被迫声明两次或为其创建一个变量。
onFinally
回调不接收任何参数。此用例恰好适用于你不关心拒绝原因或履行价值的情况,因此无需提供它。finally()
调用通常是透明的,反映了原始承诺的最终状态。例如:- 与
Promise.resolve(2).then(() => 77, () => {})
返回最终用值77
实现的承诺不同,Promise.resolve(2).finally(() => 77)
返回最终用值2
实现的承诺。 - 类似地,与
Promise.reject(3).then(() => {}, () => 88)
返回一个最终以88
值实现的 Promise 不同,Promise.reject(3).finally(() => 88)
返回一个最终以3
为理由拒绝的 Promise。
- 与
注意:
finally
回调中的throw
(或返回被拒绝的 Promise)仍然会拒绝返回的 Promise。例如,Promise.reject(3).finally(() => { throw 99; })
和Promise.reject(3).finally(() => Promise.reject(99))
都拒绝返回的 promise,原因为99
。¥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
.
与 catch()
一样,finally()
在调用它的对象上内部调用 then
方法。如果 onFinally
不是函数,则使用 onFinally
作为两个参数来调用 then()
— 对于 Promise.prototype.then()
,这意味着没有附加有用的处理程序。否则,将使用两个内部创建的函数调用 then()
,其行为如下:
¥Like 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;
}),
);
因为 finally()
调用 then()
,所以它支持子类化。此外,请注意上面的 Promise.resolve()
调用 - 实际上,onFinally()
的返回值是使用与 Promise.resolve()
相同的算法解析的,但用于构造已解析 Promise 的实际构造函数将是子类。finally()
通过 promise.constructor[Symbol.species]
得到这个构造函数。
¥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]
.
示例
使用 finally()
¥Using finally()
let isLoading = true;
fetch(myRequest)
.then((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((json) => {
/* process your JSON further */
})
.catch((error) => {
console.error(error); // this line can also throw, e.g. when console = {}
})
.finally(() => {
isLoading = false;
});
规范
Specification |
---|
ECMAScript Language Specification # sec-promise.prototype.finally |
浏览器兼容性
BCD tables only load in the browser