Web/06-JavaScript基础:ES6语法/12-Promise的静态方法.md
2021-05-25 20:54:04 +08:00

386 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## Promise 的常用 API 分类
### Promise 的实例方法
**实例方法**我们需要先 new 一个 promise 实例对象然后通过 promise 对象去调用 `then``catch``finally`方法这几个方法就是 Promise 的实例方法
Promise 的自带 API 提供了如下实例方法
- promise.then()获取异步任务的正常结果
- promise.catch()获取异步任务的异常结果
- promise.finaly()异步任务无论成功与否都会执行
### Promise 的静态方法
**静态方法**可以直接通过大写的`Promise.xxx`调用的方法这里的`xxx`就称之为静态方法
Promise 的自带 API 提供了如下静态方法
- `Promise.resolve()`
- `Promise.reject()`
- `Promsie.all()`并发处理多个异步任务所有任务都执行成功才算成功走到 resolve只要有一个失败就会走到 reject整体都算失败
- `Promise.race()`并发处理多个异步任务返回的是第一个执行完成的 promise且状态和第一个任务的状态保持一致
前面的几篇文章讲的都是 Promise **实例方法**今天这篇文章我们来详细讲一下 Promise **静态方法**
## Promise.resolve() Promise.reject()
当我们在定义一个 promise 的过程中如果涉及到异步操作那就需要通过`new Promise`的方式创建一个 Promise 实例
但有些场景下我们并没有异步操作**仍然想调用 promise.then**此时我们可以用 `Promise.resolve()` 将其包装成成功的状态同理`Promise.reject()`可以包装成失败的状态
比如说有的时候promise 里面并不涉及异步操作我只是**单纯地想通过 promise 对象返回一个字符串**有的业务就是有这样的需求那就可以通过 `Promise.reslove('字符串')` `Promise.reject('字符串')` 这种**简写**的方式返回
这两种情况我们来对比看看
1
```js
function foo(flag) {
if (flag) {
return new Promise((resolve) => {
// 这里可以做异步操作
resolve('success');
});
// return Promise.resolve('success2');
} else {
return new Promise((reslove, reject) => {
// 这里可以做异步操作
reject('fail');
});
}
}
// 执行 reslove 的逻辑
foo(true).then((res) => {
console.log(res);
});
// 执行 reject 的逻辑
foo(false).catch((err) => {
console.log(err);
});
```
2见证奇迹的时刻
```js
function foo(flag) {
if (flag) {
// Promise的静态方法直接返回字符串
return Promise.resolve('success');
} else {
// Promise的静态方法直接返回字符串
return Promise.reject('fail');
}
}
// 执行 reslove 的逻辑
foo(true).then((res) => {
console.log(res);
});
// 执行 reject 的逻辑
foo(false).catch((err) => {
console.log(err);
});
```
1 和例 2 的打印结果是一样的这两段代码的区别在于 1 里面可以封装异步任务 2 只能单纯的返回一个字符串等变量不能封装异步任务
## Promise.all()
`Promsie.all([p1, p2, p3])`并发处理多个异步任务所有任务都执行成功才算成功才会走到 then只要有一个任务失败就会马上走到 catch整体都算失败参数里传的是 多个 promise 实例组成的数组
### 语法举例
**1异步任务都执行成功时**
```js
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('执行 promise1');
resolve('promise 1 成功');
}, 1000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('执行 promise2');
resolve('promise 2 成功');
}, 2000);
});
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('执行 promise3');
resolve('promise 3 成功');
}, 3000);
});
Promise.all([promise1, promise2, promise3])
.then((res) => {
// 三个异步任务都执行成功,才会走到这里
// 这里拿到的 res是三个成功的返回结果组成的数组
console.log(JSON.stringify(res));
})
.catch((err) => {
// 只要有一个异步任务执行失败,就会马上走到这里
console.log(err);
});
```
打印结果
```js
// 1秒后
执行 promise1
// 2秒后
执行 promise2
// 3秒后
执行 promise3
["promise 1 成功","promise 2 成功","promise 3 成功"]
```
**2异步任务有至少一个执行失败时**
```js
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('执行 promise1');
resolve('promise 1 成功');
}, 1000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('执行 promise2');
// 这里通过 reject() 的方式,表示任务执行失败
reject('promise 2 失败');
}, 2000);
});
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('执行 promise3');
resolve('promise 3 成功');
}, 3000);
});
Promise.all([promise1, promise2, promise3])
.then((res) => {
// 三个异步任务都执行成功,才会走到这里
console.log('走到 then:' + JSON.stringify(res));
})
.catch((err) => {
// 只要有一个异步任务执行失败,就会马上走到这里
console.log('走到 catch:' + err);
});
```
打印结果
```js
// 1秒后
执行 promise1
// 2秒后
执行 promise2
走到 catch:promise 2 失败
// 3秒后
执行 promise3
```
可以看到 promise2 执行失败之后马上就走到了 catch而且 promise3 里的 resolve 并没有执行
### Promise.all()举例图片上传
比如说现在有一个**图片上传**的接口每次请求接口时只能上传一张图片需求是当用户连续上传完三张图片甚至是更多图片之后给用户一个上传成功的提示这个时候我们就可以使用`Promsie.all()`
## Promise.race()
`Promise.race([p1, p2, p3])`并发处理多个异步任务返回的是第一个执行完成的 promise且状态和第一个任务的状态保持一致参数里传的是多个 promise 实例组成的数组
上面这句话第一次读时可能很绕口我说的再通俗一点在多个同时执行的异步任务中先找出哪个异步任务**最先执行完成**无论是走到 resolve还是走到 reject都算执行完成然后整体的状态跟这个任务保持一致如果这个任务执行成功那整体就算成功走到 then如果这个任务执行失败那整体就算失败走到 catch
`race`的中文翻译可以理解为竞赛意思是谁先抢到名额就认定谁了无论这个人最终的结局是成功或者失败整体的结局都以这个人的结局为准
我刚开始学 Promise.race()的时候误以为它的含义是只要有一个异步执行成功整体就算成功走到 then所有任务都执行失败整体才算失败走到 catch现在想来真是大错特错过于懵懂
我们来看看各种场景的打印结果便能让你擦干泪水
### 语法举例
**场景 1所有任务都执行成功时**
```js
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('执行 promise1');
resolve('promise 1 成功');
}, 1000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('执行 promise2');
resolve('promise 2 成功');
}, 2000);
});
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('执行 promise3');
resolve('promise 3 成功');
}, 3000);
});
Promise.race([promise1, promise2, promise3])
.then((res) => {
// 只要有一个异步任务执行成功,就会走到这里
// 这里拿到的 res是第一个成功的 promise 返回的结果,不是数组
console.log(JSON.stringify(res));
})
.catch((err) => {
// 所有异步任务异步都执行失败,才会走到这里
console.log(err);
});
```
打印结果
```js
// 1秒后
执行 promise1
"promise 1 成功"
// 2秒后
执行 promise2
// 3秒后
执行 promise3
```
**场景 2第一个任务成功第二个任务失败时**
```js
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('执行 promise1');
resolve('promise 1 成功');
}, 1000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('执行 promise2');
// 第二个任务执行失败时
reject('promise 2 失败');
}, 2000);
});
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('执行 promise3');
resolve('promise 3 成功');
}, 3000);
});
Promise.race([promise1, promise2, promise3])
.then((res) => {
// 第一个完成的任务,如果执行成功,就会走到这里
console.log('走到then:' + res);
})
.catch((err) => {
// 第一个完成的任务,如果执行失败,就会走到这里
console.log('走到catch:' + err);
});
```
打印结果
```js
// 1秒后
执行 promise1
走到then:promise 1 成功
// 2秒后
执行 promise2
// 3秒后
执行 promise3
```
可以看出场景 2 的打印结果和场景 1 的打印结果是一样的因为最新执行完成的任务是成功的所以整体会马上走到 then且整体就算成功
**场景 3第一个任务失败第二个任务成功时**
```js
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('执行 promise1');
// 第一个任务执行失败时
reject('promise 1 失败');
}, 1000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('执行 promise2');
resolve('promise 2 成功');
}, 2000);
});
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('执行 promise3');
resolve('promise 3 成功');
}, 3000);
});
Promise.race([promise1, promise2, promise3])
.then((res) => {
// 第一个完成的任务,如果执行成功,就会走到这里
console.log('走到then:' + res);
})
.catch((err) => {
// 第一个完成的任务,如果执行失败,就会走到这里
console.log('走到catch:' + err);
});
```
打印结果
```js
// 1秒后
执行 promise1
走到catchpromise 1 失败
// 2秒后
执行 promise2
// 3秒后
执行 promise3
```
看清楚了没场景 3 的最终打印结果是走到了 catch任务 2 和任务 3 里的 resolve并没有继续执行
场景 3 的代码一定好好好理解
## 我的公众号
想学习**更多技能**不妨关注我的微信公众号**千古壹号**
扫一扫你将发现另一个全新的世界而这将是一场美丽的意外
![](https://img.smyhvae.com/20200102.png)