Skip to content

Commit

Permalink
update the translation of promise.finally() (#13976)
Browse files Browse the repository at this point in the history
Co-authored-by: Jason Lam <[email protected]>
Co-authored-by: A1lo <[email protected]>
  • Loading branch information
3 people committed Jul 3, 2023
1 parent 4e5f583 commit 5780c0f
Showing 1 changed file with 50 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,51 +3,83 @@ title: Promise.prototype.finally()
slug: Web/JavaScript/Reference/Global_Objects/Promise/finally
---

{{JSRef}}**`finally()`** 方法返回一个 {{jsxref("Promise")}}。在 promise 结束时,无论结果是 fulfilled 或者是 rejected,都会执行指定的回调函数。这为在 `Promise` 是否成功完成后都需要执行的代码提供了一种方式。这避免了同样的语句需要在 {{jsxref("Promise.then", "then()")}} 和 {{jsxref("Promise.catch", "catch()")}} 中各写一次的情况。
{{JSRef}}

{{jsxref("Promise")}} 实例的 **`finally()`** 方法用于注册一个在 promise 敲定(兑现或拒绝)时调用的函数。它会立即返回一个等效的 {{jsxref("Promise")}} 对象,这可以允许你[链式](/zh-CN/docs/Web/JavaScript/Guide/Using_promises#链式调用)调用其他 promise 方法。

这可以让你避免在 promise 的 {{jsxref("Promise/then", "then()")}} 和 {{jsxref("Promise/catch", "catch()")}} 处理器中重复编写代码。

{{EmbedInteractiveExample("pages/js/promise-finally.html", "taller")}}

## 语法

```js-nolint
p.finally(onFinally)
finally(onFinally)
```

### 参数

- `onFinally`
- : `Promise` 结束后调用的 {{jsxref("Function")}}
- : 一个当 promise 敲定时异步执行的函数。它的返回值将被忽略,除非返回一个被拒绝的 promise。调用该函数时不带任何参数

### 返回值

返回一个设置了 `finally` 回调函数的 {{jsxref("Promise")}} 对象
返回等效的 {{jsxref("Promise")}}。如果处理程序抛出错误或返回被拒绝的 promise,那么 `finally()` 返回的 promise 将以该值被拒绝。否则,处理程序的返回值不会影响原始 promise 的状态

## 描述

如果你想在 promise 执行完毕后无论其结果怎样都做一些处理或清理时,`finally()` 方法可能是有用的。
如果你想在 promise 敲定时进行一些处理或者清理,无论其结果如何,那么 `finally()` 方法会很有用。

`finally()` 方法类似于调用 {{jsxref("Promise/then", "then(onFinally, onFinally)")}}。然而,有几个不同之处:

- 创建内联函数时,你可以只将其传入一次,而不是强制声明两次或为其创建变量。
- `onFinally` 回调函数不接收任何参数。这种情况恰好适用于你*不关心*拒绝原因或兑现值的情况,因此无需提供它。
- `finally()` 调用通常是透明的,不会更改原始 promise 的状态。例如:
-`Promise.resolve(2).then(() => 77, () => {})` 不同,它返回一个最终会兑现为值 `77` 的 promise,而 `Promise.resolve(2).finally(() => 77)` 返回一个最终兑现为值 `2` 的 promise。
- 类似地,与 `Promise.reject(3).then(() => {}, () => 88)` 不同,它返回一个最终兑现为值 `88` 的 promise,而 `Promise.reject(3).finally(() => 88)` 返回一个最终以原因 `3` 拒绝的 promise。

> **备注:**`finally` 回调函数中抛出错误(或返回被拒绝的 promise)仍会导致返回的 promise 被拒绝。例如,`Promise.reject(3).finally(() => { throw 99; })``Promise.reject(3).finally(() => Promise.reject(99))` 都以理由 `99` 拒绝返回的 promise。
`finally()` 虽然与 `.then(onFinally, onFinally)` 类似,它们不同的是
与 {{jsxref("Promise/catch", "catch()")}} 一样,`finally()` 在内部调用其调用对象上的 `then` 方法。如果 `onFinally` 不是函数,则调用 `then()` 时使用 `onFinally` 同时作为两个参数——对于 {{jsxref("Promise.prototype.then()")}},这意味着没有附加有效的处理器。否则,`then()` 被调用时会使用两个内部创建的函数,其行为如下

- 调用内联函数时,不需要多次声明该函数或为该函数创建一个变量保存它。
- 由于无法知道 `promise` 的最终状态,所以 `finally` 的回调函数中不接收任何参数,它仅用于无论最终结果如何都要执行的情况。
-`Promise.resolve(2).then(() => {}, () => {})`(resolved 的结果为`undefined`)不同,`Promise.resolve(2).finally(() => {})` resolved 的结果为 `2`
- 同样,`Promise.reject(3).then(() => {}, () => {})` (fulfilled 的结果为`undefined`), `Promise.reject(3).finally(() => {})` rejected 的结果为 `3`
> **警告:** 这只是为了演示,而不是一个 polyfill。
> **备注:**`finally` 回调中 `throw`(或返回被拒绝的 promise)将以 `throw()` 指定的原因拒绝新的 promise.
```js
promise.then(
(value) => Promise.resolve(onFinally()).then(() => value),
(reason) =>
Promise.resolve(onFinally()).then(() => {
throw reason;
}),
);
```

因为 `finally()` 调用 `then()`,所以它支持子类化。此外,请注意上面的 {{jsxref("Promise.resolve()")}} 调用——实际上,`onFinally()` 的返回值是使用与 `Promise.resolve()` 相同的算法解决的,但用于构造解决的 promise 的实际构造函数将是子类。`finally()` 通过 [`promise.constructor[@@species]`](/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/@@species) 获取构造函数。

## 示例

### 使用 finally()

```js
let isLoading = true;

fetch(myRequest).then(function(response) {
var contentType = response.headers.get("content-type");
if(contentType && contentType.includes("application/json")) {
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(function(json) { /* process your JSON further */ })
.catch(function(error) { console.log(error); })
.finally(function() { isLoading = false; });
.then((json) => {
/* 进一步处理 JSON */
})
.catch((error) => {
console.error(error); // 这行代码也可能抛出错误,例如:when console = {}
})
.finally(() => {
isLoading = false;
});
```

## 规范
Expand All @@ -60,6 +92,7 @@ fetch(myRequest).then(function(response) {

## 参见

- [`core-js``Promise.prototype.finally` 的 Polyfill](https://github.com/zloirock/core-js#ecmascript-promise)
- {{jsxref("Promise")}}
- {{jsxref("Promise.prototype.then()")}}
- {{jsxref("Promise.prototype.catch()")}}

0 comments on commit 5780c0f

Please sign in to comment.