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:
parent
647f1221a7
commit
99b39cc230
141
docs/promise.md
141
docs/promise.md
@ -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')
|
||||
|
Loading…
x
Reference in New Issue
Block a user