最近遇到了事件循环的问题,于是决定好好的研究一番。看了一篇文章感觉讲的特别好。
https://juejin.cn/post/6844903657264136200
我们都知道event loop的执行顺序是:
- 一开始整个脚本script块会做为一个宏任务执行,(宏任务)
- 执行过程中会有一个主线程,一个宏任务队列,一个微任务队列。同步代码会按照顺序进入主线程,宏任务进入宏任务队列,微任务进入微任务队列。(微任务)
- 当执行完主线程,主线程为空时,会优先检查微任务队列,有则依次执行,直到全部执行完微任务;
- 执行完本轮的宏任务,再回到第2步,依次循环。
执行宏任务-->该宏任务产生的微任务,若微任务执行中产生了新的微任务,则继续执行微任务,微任务执行完毕,再回到宏任务进行下一轮循环。
后来自己也看了很多例子,但是疑惑点是,对于promise的then的微任务的微任务执行顺序是怎么样呢?
- 例1
new Promise((resolve, reject) => { console.log("1"); resolve(); new Promise((resolve, reject) => { console.log("2"); resolve(); }).then(() => { console.log("3"); }).then(() => { console.log("5"); }); }).then(() => { console.log("4"); })
输出结果是:1,2,3,4,5。答对了吗?
那我们来分析一下,是如何执行的呢:
首先,遇到Promise实例(标记为p1),执行该构造函数中的同步代码,立即执行,打印出:1;
接着,又遇到了Promise实例(标记为p2),打印出:2;
接着,p2的then为微任务,存入到微任务队列(入栈);------这里是指then后的一大坨。
接着,继续执行p1,p1的then也是微任务,存入到微任务队列(入栈);
好了,现在没有同步任务了,那我们开始对微任务队列动手了!!O(∩_∩)O
首先进去的是p2的微任务,那我们执行p2的then,打印出3;
接着,p2的后边还有then,继续存入微任务队列(入栈);
现在微任务队列执行到p1的then了,打印出4;
最后,就只剩下p1的第二个then了,继续执行,打印出5。
好啦!大家学废了吗?这里是我对promise的微任务的一些理解。接下来在看一个??吧!
- 例2
console.log(‘start‘) setTimeout(() => { console.log(‘time‘) }) Promise.resolve().then(() => { console.log(‘resolve‘) }) console.log(‘end‘)
输出结果为:‘start‘ ‘end‘ ‘resolve‘ ‘time‘
分析:
- 刚开始将整个脚本作为宏任务开始执行,遇到同步代码,打印出:start;
- 接着,setTimeout是异步函数,作为宏任务被放到宏任务队列,入栈;
- 依次执行到Promise.resolve().then作为一个微任务被放到微任务队列,入栈;
- 最后执行完最后一个同步代码,打印出:end;
- 本次宏任务的同步代码执行完,检查微任务,发现Promise.resolve().then,打印出:‘resolve’;直至微任务队列执行为空。
- 接下来进入宏任务队列,发现setTimeout,打印出: ‘time’。
- 接下来在看个??吧!
- 例3
const promise = new Promise((resolve, reject) => { console.log(1); console.log(2); }); promise.then(() => { console.log(3); }); console.log(4);
输出结果为:1,2,4
前边看了几个例子,这个应该很easy了吧! 这里有个点就是: 为什么没有输出3呢?
-----------------因为promise实例没有状态改变啊,只有resolve才能进入then~
promise的构造函数时同步执行,promise.then中的函数是异步执行。
从全局上下文退出前,开始收集当前层级的微任务和宏任务,然后清空微任务队列,再执行宏任务。
宏任务:包括整体代码script,setTimeout,setInterval, setImmediate
微任务: