meface/docs/article/web/js/promise.md

155 lines
4.9 KiB
Markdown
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.

---
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实例的状态变为rejectedp的状态会变成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`