155 lines
4.9 KiB
Markdown
155 lines
4.9 KiB
Markdown
---
|
||
title: Promise对象
|
||
date: 2020-12-25
|
||
author: ac
|
||
tags:
|
||
- Promise
|
||
- JavaScript
|
||
caregroies:
|
||
- Web
|
||
---
|
||
|
||
## Promise对象
|
||
|
||
> Promise 对象是JavaScript的异步解决方案,让异步操作有同步操作的流程(语法),避免了传统解决方案(回调函数和事件)一层层的嵌套回调函数。
|
||
|
||
Promise 对象是JavaScript原生提供的(ES6将其纳入语法标准)。简单理解Promise就是一个装载着一个未来才会结束的异步请求的响应结果。
|
||
|
||
```javascript
|
||
const promise = new Promise(function(resolve,reject){
|
||
|
||
})
|
||
//添加回调
|
||
promise.then(function(result){
|
||
//success
|
||
},function(error){
|
||
//failure
|
||
})
|
||
```
|
||
|
||
### Promise 状态
|
||
|
||
Promise对象代表一个异步操作,通过自身的状态来控制异步操作。Promise实例有三种状态:
|
||
|
||
- pending:异步操作未完成
|
||
- fulfilled:异步操作成功
|
||
- rejected:异步操作失败
|
||
|
||
通常将fulfilled和rejected合在一起成为resolved。
|
||
|
||
而状态的变化有两种:
|
||
|
||
- pending --> fulfilled
|
||
- pending --> rejected
|
||
|
||
Promise对象有两个特点:
|
||
|
||
1. 对象的状态不受外界影响。只有异步操作的结果可以决定Promise当前状态。
|
||
2. 状态一旦改变就不会改变,会一直保持这个结果。如果再对promise实例添加回调函数,将会立即得到这个结果。
|
||
|
||
### 实例方法 then
|
||
|
||
Promise.prototype.then(resolved,[rejected]) 的作用是为promise实例添加回调函数,返回一个新的Promise实例。
|
||
|
||
```javascript
|
||
/**
|
||
* then方法参数中的resolved函数是必填的,rejected函数是可选参数
|
||
* 支持链式写法
|
||
* 两个then方法会依次执行回调函数,第一个回调方法完成后会将结果作为参数传入第二个回调方法
|
||
*/
|
||
p1
|
||
.then(step1)
|
||
.then(step2)
|
||
.then(step3)
|
||
.then(
|
||
console.log,
|
||
console.error
|
||
);
|
||
```
|
||
|
||
p1后面的4个then方法会依次执行,但step1、step2、step3、console.log都是异步请求成功后的回调,如果step1中的请求状态变成了`rejected`,则后面的step2、step3、console.log都不会执行,由于第一个then只设置了step1,没有设置失败的回调,所以请求失败的异常会向下一个then传递,调用下一个then的`rejected`回调,最后找到`console.error`
|
||
|
||
**执行顺序**
|
||
|
||
Promise的回调函数是异步任务,会在同步任务执行完后执行。
|
||
|
||
> 事件循环是在JS引擎在同步任务执行完后,一遍一遍的循环检查异步任务队列里面的任务是否可以进入主线程中的循环检查机制。
|
||
|
||
```javascript
|
||
//定时器
|
||
setTimeout(function(){
|
||
console.log("在下一轮事件循环中");
|
||
},100);
|
||
var p2 = new Promise(function(resolve,reject){
|
||
console.log("Promise构造函数会立即执行!")
|
||
resolve();
|
||
})
|
||
p2.then(function(){
|
||
console.log("success回调");
|
||
});
|
||
console.log("在同步任务中");
|
||
|
||
---------执行结果-----------
|
||
Promise构造函数会立即执行!
|
||
在同步任务中
|
||
success回调
|
||
在下一轮事件循环中
|
||
```
|
||
|
||
正常的回调函数是追加到下一轮事件循环中的,但Proimse中的回调是当做微任务添加在本轮事件循环中末尾。
|
||
|
||
> 定时器setTimeout和setInteral的运行机制是回调函数移除本轮事件循环,等到下一轮事件循环,检查是否到达指定时间,若到达则执行。
|
||
|
||
|
||
|
||
### 实例方法 catch
|
||
|
||
Promise.prototype.catch()方法是用来指定发生错误时的回调函数。
|
||
|
||
可以理解成`.then(null,rejected)`或`.then(undefined,rejected)`的别名。
|
||
|
||
```javascript
|
||
p1.then(function(r){
|
||
|
||
}).then(null,function(e){
|
||
|
||
})
|
||
//等价于
|
||
p1.then(function(r){
|
||
|
||
}).cath(function(e){
|
||
|
||
})
|
||
```
|
||
|
||
Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。如果Promise实例没有在then方法中设置rejected函数作为请求失败的回调,同时也没有设置catch方法,则promise实例将会“吃掉”错误,不会反应到外部,但会成为未捕获的错误。
|
||
|
||
|
||
|
||
### 静态方法 all
|
||
|
||
Promise.all()方法是接收一个Promise实例数组,将多个Promise实例封装成一个Promise实例。
|
||
|
||
```javascript
|
||
const p = Promise.all([p1,p2,p3,p4]);
|
||
```
|
||
|
||
只有当数组中的所有Promise实例的状态为`fulfilled`时,p的状态才会变成`fulfilled`。返回的结果是一个数组,其成员依次是Promise实例成员的`fulfilled`状态的响应结果。
|
||
|
||
只要数组中的任意一个Promise实例的状态变为rejected,p的状态会变成rejected。
|
||
|
||
注意:
|
||
|
||
如果数组中的Promise实例有添加失败的rejected回调或是有添加cath方法,则该rejected状态的Promise实例会先执行失败的回调或catch方法返回一个新的状态为resolved的Promise实例,最终p接收的是这个新的Promise实例。
|
||
|
||
|
||
|
||
|
||
|
||
### 参考文章
|
||
|
||
[1] [Promise 对象](https://wangdoc.com/javascript/async/promise.html) `https://wangdoc.com/javascript/async/promise.html`
|
||
|
||
[2] [ES6入门](https://es6.ruanyifeng.com/#docs/promise) `https://es6.ruanyifeng.com/#docs/promise`
|
||
|