promise背景
promise之前首先要知道因为JS是单线程的,而JS中一些常见的比如网络请求等都需要异步操作来完成,ES6之前使用回调函数解决这个问题,但是回调函数阅读不方便还会造成回调地狱,ES6中新增了解决这个问题的方法也就是Promise,这也是promise出现的背景,进一步的ES7中使用async await更进一步的解决这个问题,也是JS中异步操作的终极解决方案
1. promise的几个API
promise.resolve(1)
promise.reject(1)
promise.all([promise1,promise2,promise3])
promise.race([promise1,promise2,promise3])
1. promise的三个状态
pending,表示进行中
fulfilled也是resolved,表示成功
rejected,表示失败
2.promise的状态变化
只能从pending->resolved或者pending->rejected
promise的状态改变后就不会再次改变会一直保持这个状态,而且promise不会受到外界的影响,只会受到异步操作的结果的影响
3.promise的基本用法
new Promise((resolve,reject)=>{
if(true){
resolve(value);
}else{
reject(err);
}
}).then(
value=>{};
reason=>{};
).catch(
)
新建一个promise构造函数,函数接受一个函数作为参数,同时该函数有两个参数,reject和resolve
执行异步操作
成功执行resolve(),状态变成resolved状态
失败执行reject(),状态变成rejected状态
无论成功还是失败都可以通过.then()指定成功和失败的回调函数,catch只能调用失败的回调函数
promise是同步执行,then是异步执行
5.JS中的同步与异步
同步就是指放在主线程中执行的任务,只有主线程中上一个任务执行完毕才执行下一个同步任务
异步不是在主线程中执行,而是将其放在任务队列中执行,只有等到主线程执行完毕,任务队列中的任务才放入主线程执行
而比较重要的一点是任务队列又分为宏队列和微队列
executor是promise的执行器函数,是同步执行的函数,也就是说promise是同步,而promise的回调函数是异步
6.宏队列和微队列
宏队列:用来保存待执行的宏任务,,比如定时器、DOM回调、ajax回调
微队列:用来保存待执行的微任务,比如:promise的回调/mutationObserver的回调
执行顺序:每次取出宏任务之前要先把微任务全部取出来放到栈里面处理掉,然后再执行宏任务
知道了同步与异步还有队列之间的关系做一些题目就比较轻松了
题目一:
<script type="text/javascript">
new Promise((resolve,reject)=>{
console.log("1");
resolve();
console.log("2");
}).then(()=>{
console.log("3");
})
console.log("4");
//输出1 2 4 3
</script>
理解:promise的立即执行函数是同步执行,从上到下,先打印1,resolve()函数之后状态从pending->resolved状态,输出2,因为then中回调函数是异步执行且是微队列所以要等到同步任务执行完毕才执行,所以打印4,同步任务执行完成,执行异步任务,打印3,1 2 4 3
题目二
理解:定时器是异步执行宏队列,暂不执行,console.log()是同步执行,所以先打印promise1,此时promise1的状态是初始状态pending,然后打印promise2,也是pending状态,此时同步全部执行完成,开始执行异步任务,执行resolve()将prmise的pending->resolved,promise抛出一个错误,下面打印promise1,和promise2,且是rejected状态
题目三
理解:这个题目重点是要知道promise的状态只会改变一次,所以success1只有这一个成功执行,只执行then中的成功回调函数,打印,then:success1
题目四
理解:这个题目的重点是要知道promise能实现链式调用是因为then中每次都会返回一个新的promise并将值传递出去,返回任意一个不是promise的值都会被包裹从promise对象,return 2其实就是return promise.resolve(2)的意思,所以resolve(1)后将pending->resolved调用then()中的成功函数回调,打印1,再将resolve(2)传递出去,执行then()中的打印2,所以1 2
题目五
then中return错误不会被catch捕获,只有throw new error才会被捕获,或者retuen promise.reject(),所以是被当初return promise.resolve("Error;error!")传递出去
题目六
理解:then或者catch中不能返回promise本身,会死循环错误
题目7
理解:这个的重点是then或者catch中如果传递的不是函数会发生传透/穿透,直到找到可以执行成功回调函数