JS时间循环宏任务微任务 讲解+面试题
什么是事件循环?
事实上我把事件循环理解成我们编写的JavaScript和浏览器或者Node之间的一个桥梁
浏览器的事件循环是一个我们编写的JavaScript代码和浏览器API调用(setTimeout/AJAX/监听事件等)的一个桥梁, 桥梁之间他们通过回调函数进行沟通。
Node的事件循环是一个我们编写的JavaScript代码和系统调用(file system、network等)之间的一个桥梁, 桥梁 之间他们通过回调函数进行沟通的
JS代码执行流程
- 定义变量name;
- 执行log函数,函数会被放入到调用栈中执 行;
- 调用bar()函数,被压入到调用栈中,但是执 行未结束;
- bar因为调用了sum,sum函数被压入到调 用栈中,获取到结果后出栈;
- bar获取到结果后出栈,获取到结果result;
- 将log函数压入到调用栈,log被执行,并且 出栈
浏览器中事件循环
如果执行JS中存在异步操作,例如setTimeout(),则会被放入调用栈中,执行会结束,不会阻塞后面代码运行
其实内部调用 web API,在合适的时机将函数加入到事件队列中
事件队列中的函数会被放入调用栈,然后被执行。
宏任务、微任务
事件循环中事实上有两个队列
- 宏任务队列(macrotask queue):ajax、setTimeout、setInterval、DOM监听、UI Rendering等
- 微任务队列(microtask queue):Promise的then回调、 Mutation Observer API、queueMicrotask()等
那么事件循环对于两个队列的优先级是怎么样的呢?
- main script中的代码优先执行(编写的顶层script代码);
- 在执行任何一个宏任务之前(不是队列,是一个宏任务),都会先查看微任务队列中是否有任务需要执行
- 也就是宏任务执行之前,必须保证微任务队列是空的;
- 如果不为空,那么久优先执行微任务队列中的任务(回调)
面试题
1
setTimeout(function () { console.log("set1"); new Promise(function (resolve) { resolve(); }).then(function () { new Promise(function (resolve) { resolve(); }).then(function () { console.log("then4"); }); console.log("then2"); }); }); new Promise(function (resolve) { console.log("pr1"); resolve(); }).then(function () { console.log("then1"); }); setTimeout(function () { console.log("set2"); }); console.log(2); queueMicrotask(() => { console.log("queueMicrotask1") }); new Promise(function (resolve) { resolve(); }).then(function () { console.log("then3"); }); // pr1 // 2 // then1 // queuemicrotask1 // then3 // set1 // then2 // then4 // set2
2
async function async1 () { console.log('async1 start') await async2(); console.log('async1 end') } async function async2 () { console.log('async2') } console.log('script start') setTimeout(function () { console.log('setTimeout') }, 0) async1(); new Promise (function (resolve) { console.log('promise1') resolve(); }).then (function () { console.log('promise2') }) console.log('script end') // script start // async1 start // async2 // promise1 // script end // aysnc1 end // promise2 // setToueout
注意:
Promise中的为同步代码块,then后为异步 微任务
Async 函数中:await前的可以看做Promise外部的diamante
await相当于在执行Promise中的为同步代码块
await后的相当于在执行then的回调 微任务
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~