机制分析"/>
JS Event Loop事件执行机制分析
题目一(setTimeout + setTimeout 时间处理 + promise)
function log1() {console.log('1');}log1();setTimeout(function log2() {console.log('2');})setTimeout(function log3() {console.log('3');})setTimeout(function log4() {console.log('4');}, 1)setTimeout(function log5() {console.log('5');}, 30)new Promise(function log6(resolve) {console.log('6');resolve('7');console.log('8');}).then(function log8(res) {console.log(res);}).then(function log9() {console.log('9');}).then(function log10() {console.log('10');})setTimeout(function log11() {console.log('11');})Promise.resolve().then(function log12() {console.log('12');})
输出:1 6 8 7 12 9 10 2 3 4 11 5 或 1 6 8 7 12 9 10 2 3 11 4 5
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nU6Uxbu4-1620641683120)(image/未命名文件 (2)].png)
-
log1同步任务,入队列
-
log2、log3是setTimeout,宏任务,入队列
-
log4延时了1ms执行,这里就有区别了,不同浏览器的处理是不一致的,1ms的意思是1ms后对应的事件添加到了执行栈,具体执行要看栈里的资源执行情况,具体可以参考后面的《setTimeout和setInterval的最小时间问题》
-
log5延时了30ms执行,基本其他逻辑都执行完了,所以最后输出
-
log6是promise的同步执行
-
log9、log10之前的then没有返回信息,执行注册,微任务
-
log12微任务添加,log11和log4的执行先后顺序是不定的,涉及到浏览器对延时的处理,具体可以参考后面的 《setTimeout和setInterval的最小时间问题》
-
log12和log7相同,promise的then是微任务,then直接执行的话会插入到队列首,具体可以参考后面的《图解promise》
题目二(promise 有返回值)
new Promise(function log1(resolve, reject) {console.log('1');resolve();
})
.then(function log2() {console.log('2');return new Promise((resolve, reject) => {console.log('3');resolve();}).then(() => {console.log('4');}).then(() => {console.log('5');});
})
.then(() => {console.log('6');
});
输出:1 2 3 4 5 6
-
1为同步,resolve同步执行了2,返回了promise,输出了3
-
问题在于4、5、6的输出顺序上,6在等待return的promise处理结果,相当于又开启了一个event loop循环,内部执行后输出了4、5后输出6
题目三(promise 无返回值)
new Promise(function log1(resolve, reject) {console.log('1');resolve();
})
.then(function log2() {console.log('2');new Promise((resolve, reject) => {console.log('3');resolve();}).then(() => {console.log('4');}).then(() => {console.log('5');});
})
.then(() => {console.log('6');
});
输出:1 2 3 4 6 5
- 这个没有return值,后续值会优先注册输出,6先于5输出
相关知识点
-
执行任务分同步任务和异步任务,异步任务分宏任务和微任务
-
setTimeout和setInterval为宏任务,promise的then为微任务
-
promise的处理要注意,then内返回了值的后续会开启循环执行,不加return的话后续then只是注册执行
-
setTimeout是固定时间后将函数入栈,不同浏览器的时间表现有差异,不是设置了多少延时就是多久后执行
参考文献
详解JavaScript中的Event Loop(事件循环)机制
深度揭秘 Promise 微任务注册和执行过程
setTimeout 和 setInterval最小执行时间问题
图解 Promise 实现原理(一)—— 基础实现
更多推荐
JS Event Loop事件执行机制分析
发布评论