千家信息网

Javascript中Microtask和Macrotask实例分析

发表于:2025-01-18 作者:千家信息网编辑
千家信息网最后更新 2025年01月18日,这篇文章主要讲解了"Javascript中Microtask和Macrotask实例分析",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"Javascri
千家信息网最后更新 2025年01月18日Javascript中Microtask和Macrotask实例分析

这篇文章主要讲解了"Javascript中Microtask和Macrotask实例分析",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"Javascript中Microtask和Macrotask实例分析"吧!

首先我们来看一道题目,如下javascript代码,执行后会在控制台打印出什么内容?

async function async1() {   console.log('async1 start');   await async2();   console.log('async1 end'); } async function async2() {   console.log('async2 start');   return new Promise((resolve, reject) => {     resolve();     console.log('async2 promise');   }) } console.log('script start'); setTimeout(function() {   console.log('setTimeout'); }, 0);   async1(); new Promise(function(resolve) {   console.log('promise1');   resolve(); }).then(function() {   console.log('promise2'); }).then(function() {   console.log('promise3'); }); console.log('script end')

说实话,真正能在面试中把这道题目答对的前端工程师凤毛麟角。我们先来瞧一下答案吧。把以上代码存到test.js文件中,并用node执行一下,结果如下:

如果把以上代码贴到一个网页中的script标签里面,然后打开这个网页,再打开控制台,可以看到如下输出(Chrome 64位 63.0.3239.84):

结果和node打印的一模一样。那么为什么是这个顺序呢?

我们都知道js的单线程特性(html5的web worker不算在内~)以及良好的异步支持。在单线程的前提下,异步任务到底什么时候开始执行,其实是有两个队列来进行管理,即Macrotask和Microtask(只有一个字母的差距,不要认错……)。在当前正在执行的线程中,如果碰到属于Macrotask的异步任务,则放入Macrotask队列;碰到Microtask的异步任务则放入Microtask队列。注意这里只是把任务放入队列,并不会执行它。等到当前主线程任务执行完毕之后,会依次从Microtask队列中取出任务执行,在执行期间当然还是遵循碰到异步任务放入相应队列的原则。等到Microtask任务全部执行过了,此时再从Macrotask队列中取出一个任务执行。

属于Macrotask的任务有:

setTimeout,setInteveral,script标签,I/O,UI渲染

属于Microtask的任务有:

Promise,async/await,process.nextTick,Object.observe,MutationObserver

(事实上,即使同样是Microtask,内部也是有优先级的差别的,例如NodeJS的实现上,process.nextTick比Promise要先执行。相关问题可以瞧瞧这个连接:https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/ 。反正我瞧到一半就放弃了,好在async/await和Promise没有优先级差别)

然后我们来分析一下本题中的执行顺序:

【1】第15行执行,打印出script start

【2】第16至18行,把回调任务放入Macrotask (目前Macrotask:第16行setTimeout,Microtask:空)

【3】第20行,执行async1函数,先打印出第2行的async1 start

【4】第3行的async2先执行,打印出第8行的async2 start

【5】第9行至第12行遇到Promise,先打印出第11行的async2 promise(注意不管你resolve写在new Promise的函数什么位置,都跟写到最后一句一样!)

【6】第3行的async2返回了Promise,并且async2前面有await修饰,因此后面第4行的任务被放到Microtask(目前Macrotask:第16行setTimeout,Microtask:第4行)

【7】第22至25行,打印出promise1,并把第26行放入Microtask,注意第28行还没执行到,所以这行什么都不做(目前Macrotask:第16行setTimeout,Microtask:第4行,第26行)

【8】第30行打印script end(目前Macrotask:第16行setTimeout,Microtask:第4行,第26行)

【9】脚本主线程执行结束,现在拿出来一个Microtask,即第4行,打印async1 end(目前Macrotask:第16行setTimeout,Microtask:第26行)

【10】再拿出来一个Microtask,即第26行,打印promise2,此时由于第26行后面跟着then,所以把第28行插入Microtask(目前Macrotask:第16行setTimeout,Microtask:第28行)

【11】再拿出来一个Microtask,即第28行,打印promise3(目前Macrotask:第16行的setTimeout,Microtask:空)

【12】Microtask没有了,执行下一个Macrotask,即第16行的setTimeout,打印setTimeout,结束

需要注意的是,以下两种写法,效果是一模一样的(resolve的位置无所谓):

写法1:new Promise((resolve, reject) => {  console.log('1111');  resolve();  console.log('2222');}); 写法2:new Promise((resolve, reject) => {  console.log('1111');  console.log('2222');  resolve();});

另外,对于Promise的链式调用,如new Promise(....).then(...).then(...)....,一次只放第一个then的内容进入Microtask,等第一个then执行的时候,会把第二个then放入Microtask,而不是一次把两个then都放进去。

感谢各位的阅读,以上就是"Javascript中Microtask和Macrotask实例分析"的内容了,经过本文的学习后,相信大家对Javascript中Microtask和Macrotask实例分析这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

任务 队列 分析 线程 实例 实例分析 内容 代码 写法 学习 一模一样 两个 优先级 位置 函数 差别 控制台 时候 标签 结果 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 数据库查询某一列是否为空 文件服务器权限控制 深圳大楼震动 服务器 江苏优势软件开发价目表 乌镇互联网大会金融科技 数据库插入死锁原因 软件开发从底层开始开发的优劣 广东交友软件开发定制 安徽云端服务器租用虚拟主机 如何为网络安全做出贡献 北京橙色云互联网科技公司 关系数据库中主键的作用 苹果激活无服务器 威博网络技术有限公司 自己手机的网络安全密匙如何查看 计算机考试网络安全三级 上海电商软件开发中心 浙江hpe刀片服务器云服务器 我的世界服务器创建手机版 红帽杯网络安全大赛题目 监督网络安全的政府机构是 关于网络安全的认知实习报告 星界边境服务器管理 2021年4月自考数据库真题 网络安全通报预警系统 jsp数据库获取头像 威博网络技术有限公司 时序数据库表 网络安全有几条规则 我的世界服务器创建手机版
0