1
0
mirror of https://github.com/ruanyf/es6tutorial.git synced 2025-05-27 20:32:21 +00:00

docs(Promise): edit Promise

This commit is contained in:
ruanyf 2019-10-06 20:11:13 +08:00
parent 647f1221a7
commit 99b39cc230

View File

@ -567,13 +567,13 @@ Promise.reject(3).finally(() => {})
## Promise.all()
`Promise.all`方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
`Promise.all()`方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
```javascript
const p = Promise.all([p1, p2, p3]);
```
上面代码中,`Promise.all`方法接受一个数组作为参数,`p1``p2``p3`都是 Promise 实例,如果不是,就会先调用下面讲到的`Promise.resolve`方法,将参数转为 Promise 实例,再进一步处理。`Promise.all`方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。
上面代码中,`Promise.all()`方法接受一个数组作为参数,`p1``p2``p3`都是 Promise 实例,如果不是,就会先调用下面讲到的`Promise.resolve`方法,将参数转为 Promise 实例,再进一步处理。另外,`Promise.all()`方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。
`p`的状态由`p1``p2``p3`决定,分成两种情况。
@ -662,7 +662,7 @@ Promise.all([p1, p2])
## Promise.race()
`Promise.race`方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。
`Promise.race()`方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。
```javascript
const p = Promise.race([p1, p2, p3]);
@ -670,7 +670,7 @@ const p = Promise.race([p1, p2, p3]);
上面代码中,只要`p1``p2``p3`之中有一个实例率先改变状态,`p`的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给`p`的回调函数。
`Promise.race`方法的参数与`Promise.all`方法一样,如果不是 Promise 实例,就会先调用下面讲到的`Promise.resolve`方法,将参数转为 Promise 实例,再进一步处理。
`Promise.race()`方法的参数与`Promise.all()`方法一样,如果不是 Promise 实例,就会先调用下面讲到的`Promise.resolve()`方法,将参数转为 Promise 实例,再进一步处理。
下面是一个例子,如果指定时间内没有获得结果,就将 Promise 的状态变为`reject`,否则变为`resolve`
@ -689,9 +689,138 @@ p
上面代码中,如果 5 秒之内`fetch`方法无法返回结果,变量`p`的状态就会变为`rejected`,从而触发`catch`方法指定的回调函数。
## Promise.allSettled()
`Promise.allSettled()`方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只有等到所有这些参数实例都返回结果,不管是`fulfilled`还是`rejected`,包装实例才会结束。该方法由[ES2020](https://github.com/tc39/proposal-promise-allSettled) 引入。
```javascript
const promises = [
fetch('/api-1'),
fetch('/api-2'),
fetch('/api-3'),
];
await Promise.allSettled(promises);
removeLoadingIndicator();
```
上面代码对服务器发出三个请求,等到三个请求都结束,不管请求成功还是失败,加载的滚动图标就会消失。
该方法返回的新的 Promise 实例,一旦结束,状态总是`fulfilled`,不会变成`rejected`。状态变成`fulfilled`Promise 的监听函数接收到的参数是一个数组,每个成员对应一个传入`Promise.allSettled()`的 Promise 实例。
```javascript
const resolved = Promise.resolve(42);
const rejected = Promise.reject(-1);
const allSettledPromise = Promise.allSettled([resolved, rejected]);
allSettledPromise.then(function (results) {
console.log(results);
});
// [
// { status: 'fulfilled', value: 42 },
// { status: 'rejected', reason: -1 }
// ]
```
上面代码中,`Promise.allSettled()`的返回值`allSettledPromise`,状态只可能变成`fulfilled`。它的监听函数接收到的参数是数组`results`。该数组的每个成员都是一个对象,对应传入`Promise.allSettled()`的两个 Promise 实例。每个对象都有`status`属性,该属性的值只可能是字符串`fulfilled`或字符串`rejected``fulfilled`时,对象有`value`属性,`rejected`时有`reason`属性,对应两种状态的返回值。
下面是返回值用法的例子。
```javascript
const promises = [ fetch('index.html'), fetch('https://does-not-exist/') ];
const results = await Promise.allSettled(promises);
// 过滤出成功的请求
const successfulPromises = results.filter(p => p.status === 'fulfilled');
// 过滤出失败的请求,并输出原因
const errors = results
.filter(p => p.status === 'rejected')
.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()
`Promise.any()`方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只要参数实例有一个变成`fulfilled`状态,包装实例就会变成`fulfilled`状态;如果所有参数实例都变成`rejected`状态,包装实例就会变成`rejected`状态。该方法目前是一个第三阶段的[提案](https://github.com/tc39/proposal-promise-any) 。
`Promise.all()``Promise.race()`方法很像,只有一点不同,就是不会因为某个 Promise 变成`rejected`状态而结束。
```javascript
const promises = [
fetch('/endpoint-a').then(() => 'a'),
fetch('/endpoint-b').then(() => 'b'),
fetch('/endpoint-c').then(() => 'c'),
];
try {
const first = await Promise.any(promises);
console.log(first);
} catch (error) {
console.log(error);
}
```
上面代码中,`Promise.any()`方法的参数数组包含三个 Promise 操作。其中只要有一个变成`fulfilled``Promise.any()`返回的 Promise 对象就变成`fulfilled`。如果所有三个操作都变成`rejected`,那么就会`await`命令就会抛出错误。
`Promise.any()`抛出的错误,不是一个一般的错误,而是一个 AggregateError 实例。它相当于一个数组,每个成员对应一个被`rejected`的操作所抛出的错误。下面是 AggregateError 的实现示例。
```javascript
new AggregateError() extends Array -> AggregateError
const err = new AggregateError();
err.push(new Error("first error"));
err.push(new Error("second error"));
throw err;
```
捕捉错误时,如果不用`try...catch`结构和 await 命令,可以像下面这样写。
```javascript
Promise.any(promises).then(
(first) => {
// Any of the promises was fulfilled.
},
(error) => {
// All of the promises were rejected.
}
);
```
下面是一个例子。
```javascript
var resolved = Promise.resolve(42);
var rejected = Promise.reject(-1);
var alsoRejected = Promise.reject(Infinity);
Promise.any([resolved, rejected, alsoRejected]).then(function (result) {
console.log(result); // 42
});
Promise.any([rejected, alsoRejected]).catch(function (results) {
console.log(results); // [-1, Infinity]
});
```
## Promise.resolve()
有时需要将现有对象转为 Promise 对象,`Promise.resolve`方法就起到这个作用。
有时需要将现有对象转为 Promise 对象,`Promise.resolve()`方法就起到这个作用。
```javascript
const jsPromise = Promise.resolve($.ajax('/whatever.json'));
@ -699,7 +828,7 @@ const jsPromise = Promise.resolve($.ajax('/whatever.json'));
上面代码将 jQuery 生成的`deferred`对象,转为一个新的 Promise 对象。
`Promise.resolve`等价于下面的写法。
`Promise.resolve()`等价于下面的写法。
```javascript
Promise.resolve('foo')