diff --git a/docs/promise.md b/docs/promise.md index ea5b047..0474cee 100644 --- a/docs/promise.md +++ b/docs/promise.md @@ -691,7 +691,27 @@ p ## Promise.allSettled() -`Promise.allSettled()`方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只有等到所有这些参数实例都返回结果,不管是`fulfilled`还是`rejected`,包装实例才会结束。该方法由 [ES2020](https://github.com/tc39/proposal-promise-allSettled) 引入。 +有时候,我们希望等到一组异步操作都结束了,不管每一个操作是成功还是失败,再进行下一步操作。但是,现有的 Promise 方法很难实现这个要求。 + +`Promise.all()`方法只适合所有异步操作都成功的情况,如果有一个操作失败,就无法满足要求。 + +```javascript +const urls = [url_1, url_2, url_3]; +const requests = urls.map(x => fetch(x)); + +try { + await Promise.all(requests); + console.log('所有请求都成功。'); +} catch { + console.log('至少一个请求失败,其他请求可能还没结束。'); +} +``` + +上面示例中,`Promise.all()`可以确定所有请求都成功了,但是只要有一个请求失败,它就会报错,而不管另外的请求是否结束。 + +为了解决这个问题,[ES2020](https://github.com/tc39/proposal-promise-allSettled) 引入了`Promise.allSettled()`方法,用来确定一组异步操作是否都结束了(不管成功或失败)。所以,它的名字叫做”Settled“,包含了”fulfilled“和”rejected“两种情况。 + +`Promise.allSettled()`方法接受一个数组作为参数,数组的每个成员都是一个 Promise 对象,并返回一个新的 Promise 对象。只有等到参数数组的所有 Promise 对象都发生状态变更(不管是`fulfilled`还是`rejected`),返回的 Promise 对象才会发生状态变更。 ```javascript const promises = [ @@ -704,9 +724,9 @@ await Promise.allSettled(promises); removeLoadingIndicator(); ``` -上面代码对服务器发出三个请求,等到三个请求都结束,不管请求成功还是失败,加载的滚动图标就会消失。 +上面示例中,数组`promises`包含了三个请求,只有等到这三个请求都结束了(不管请求成功还是失败),`removeLoadingIndicator()`才会执行。 -该方法返回的新的 Promise 实例,一旦结束,状态总是`fulfilled`,不会变成`rejected`。状态变成`fulfilled`后,Promise 的监听函数接收到的参数是一个数组,每个成员对应一个传入`Promise.allSettled()`的 Promise 实例。 +该方法返回的新的 Promise 实例,一旦发生状态变更,状态总是`fulfilled`,不会变成`rejected`。状态变成`fulfilled`后,它的回调函数会接收到一个数组作为参数,该数组的每个成员对应前面数组的每个 Promise 对象。 ```javascript const resolved = Promise.resolve(42); @@ -723,9 +743,21 @@ allSettledPromise.then(function (results) { // ] ``` -上面代码中,`Promise.allSettled()`的返回值`allSettledPromise`,状态只可能变成`fulfilled`。它的监听函数接收到的参数是数组`results`。该数组的每个成员都是一个对象,对应传入`Promise.allSettled()`的两个 Promise 实例。每个对象都有`status`属性,该属性的值只可能是字符串`fulfilled`或字符串`rejected`。`fulfilled`时,对象有`value`属性,`rejected`时有`reason`属性,对应两种状态的返回值。 +上面代码中,`Promise.allSettled()`的返回值`allSettledPromise`,状态只可能变成`fulfilled`。它的回调函数接收到的参数是数组`results`。该数组的每个成员都是一个对象,对应传入`Promise.allSettled()`的数组里面的两个 Promise 对象。 -下面是返回值用法的例子。 +`results`的每个成员是一个对象,对象的格式是固定的,对应异步操作的结果。 + +```javascript +// 异步操作成功时 +{status: 'fulfilled', value: value} + +// 异步操作失败时 +{status: 'rejected', reason: reason} +``` + +成员对象的`status`属性的值只可能是字符串`fulfilled`或字符串`rejected`,用来区分异步操作是成功还是失败。如果是成功(`fulfilled`),对象会有`value`属性,如果是失败(`rejected`),会有`reason`属性,对应两种状态时前面异步操作的返回值。 + +下面是返回值的用法例子。 ```javascript const promises = [ fetch('index.html'), fetch('https://does-not-exist/') ]; @@ -740,22 +772,6 @@ const errors = results .map(p => p.reason); ``` -有时候,我们不关心异步操作的结果,只关心这些操作有没有结束。这时,`Promise.allSettled()`方法就很有用。如果没有这个方法,想要确保所有操作都结束,就很麻烦。`Promise.all()`方法无法做到这一点。 - -```javascript -const urls = [ /* ... */ ]; -const requests = urls.map(x => fetch(x)); - -try { - await Promise.all(requests); - console.log('所有请求都成功。'); -} catch { - console.log('至少一个请求失败,其他请求可能还没结束。'); -} -``` - -上面代码中,`Promise.all()`无法确定所有请求都结束。想要达到这个目的,写起来很麻烦,有了`Promise.allSettled()`,这就很容易了。 - ## Promise.any() ES2021 引入了[`Promise.any()`方法](https://github.com/tc39/proposal-promise-any)。该方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例返回。