JavaScript系列—宏任务和微任务
发布日期:2021-05-06 19:38:56 浏览次数:17 分类:技术文章

本文共 2028 字,大约阅读时间需要 6 分钟。

看这篇博文之前,先看一下下面的文章吧

《JavaScript 运行机制详解:再谈Event Loop》

本文有参考,微信搜索《重学前端 --- Promise里的代码为什么比setTimeout先执行?》

关于宏任务和微任务

先看几道题吧

var r = new Promise(function(resolve, reject){    console.log("a");    resolve()  });  setTimeout(()=>console.log("d"), 0)  r.then(() => console.log("c"));  console.log("b")

打印a b c d

再回头来看看开头的一段代码,会不会豁然开朗了呢。JS 引擎首先会把Promise对象 和 console.log("b") 两个微观任务存入执行栈,把 setTimeout(宏观任务)存入 “任务队列”

所以在输出 a 和 b 以后并不会按照预期那样立即从 “任务队列” 中读取 setTimeout,因为 then方法是微观任务Promise对象的回调函数,先于 setTimeout 执行

Promise.resolve().then(()=>{    console.log('1')    setTimeout(()=>{      console.log('2')    },0)  })  setTimeout(()=>{    console.log('3')    Promise.resolve().then(()=>{      console.log('4')    })  },0)

打印1 3 4 2

在交流群中看到有的小伙伴还是不太清楚正确的执行顺序,基于前面的介绍,大致的分析过程及草图如下:

 

1(红色):JS 引擎会把微观任务Promise存入执行栈,把宏观任务setTimeout存入 “任务队列”

2(绿色):主线程率先运行执行栈中的代码,依次输入1,然后把绿框的setTimeout存入 “任务队列”

3(蓝色):执行栈清空以后,会率先读取 “任务队列” 中最早存入的setTimeout(红框的那个),并把这个定时器存入栈中,开始执行。这个定时器中的代码都是微观任务,所以可以一次性执行,依次输出3 和 4

4(紫色):重复第3步的操作,读取 “任务队列” 中最后存入的setTimeout(绿框的那个),输出2

所以最终的输出结果就是 1 3 4 2

 

 

Promise.resolve().then(()=>{    console.log('1')    setTimeout(()=>{      console.log('2')    },0)  })  setTimeout(()=>{    console.log('3')    Promise.resolve().then(()=>{      console.log('4')    })  }, 3000)

打印1 2 3 4

setTimeout(function(){console.log(4)},0);     new Promise(function(resolve){     console.log(1)     for( var i=0 ; i<10000 ; i++ ){       i==9999 && resolve()     }     console.log(2)   }).then(function(){     console.log(5)   });   console.log(3);

另外一个会让人感到迷惑的地方就是 resolve回调函数内部的那几行代码,输出1以后接着跑1000次循环才调用resolve方法,其实resolve()的意思是把 Promise对象实例的状态从pending变成 fulfilled(即成功)

成功的回调就是对应的then方法。所以resolve() 后面的 console.log(2) 会先执行,因为 resolve() 回调函数是在本轮事件循环的末尾执行 (关于这部分内容,可以参考  Promise对象 一文)

打印1 2 3 5 4

setTimeout(function(){console.log(4)},0);     new Promise(function(resolve){     console.log(1)     for( var i=0 ; i<10000 ; i++ ){      //  i==9999 && resolve()     }     console.log(2)   }).then(function(){     console.log(5)   });   console.log(3);

打印1 2 3 4

上一篇:css系列—sass,scss,less,stylus的比较
下一篇:web前端面试一从输入url到看到页面发生了什么

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2025年03月11日 05时59分39秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

编写测试用例的实用小技巧 2019-03-03
c语言贪吃蛇控制台版 2019-03-03
Windows10 下springboot应用无法被外部网络访问 2019-03-03
报错:在IDEA中springboot项目操作数据库,配置文件驱动com.mysql.cj.jdbc.Driver标红 2019-03-03
redis报错(error) NOAUTH Authentication required.解决办法 2019-03-03
【树形dp】P1273 有线电视网 2019-03-03
【最短路】P4408 [NOI2003]逃学的小孩 2019-03-03
2020电工(初级)考试及电工(初级)考试软件 2019-03-03
2020N1叉车司机模拟考试题库及N1叉车司机复审模拟考试 2019-03-03
2020年制冷与空调设备运行操作答案解析及制冷与空调设备运行操作考试总结 2019-03-03
2020年保育员(初级)考试资料及保育员(初级)新版试题 2019-03-03
2020年茶艺师(高级)考试内容及茶艺师(高级)考试申请表 2019-03-03
2021年重氮化工艺考试题库及重氮化工艺考试报名 2019-03-03
2021年车工(高级)考试总结及车工(高级)试题及答案 2019-03-03
2021年压力焊证考试及压力焊实操考试视频 2019-03-03
2021年低压电工考试及低压电工考试申请表 2019-03-03
2021年低压电工考试及低压电工考试申请表 2019-03-03
2021年A特种设备相关管理(电梯)考试APP及A特种设备相关管理(电梯)复审考试 2019-03-03
2021年N1叉车司机考试题及N1叉车司机复审模拟考试 2019-03-03
2021年危险化学品经营单位主要负责人考试APP及危险化学品经营单位主要负责人多少钱 2019-03-03