JS事件循环——宏任务与微任务执行顺序
最近被事件循环搞蒙了,写一篇来巩固一下,下面这段代码输出顺序是什么:
import { nextTick } from 'vue'
new Promise((resolve, reject) => {
console.log(1)
resolve(2)
console.log(3)
}).then(val => {
console.log(val)
})
setTimeout(() => {
console.log(4)
nextTick(() => {
console.log(5)
})
console.log(6)
}, 0);
nextTick(() => {
console.log(7)
})
console.log(8)
输出顺序是1,3,8,2,7,4,6,5,这个答案得从js事件循环开始说。
JS的事件循环机制
事件循环(vent Loops)用于协调事件、用户交互、JavaScript 脚本、DOM 渲染、网络请求等等的执行顺序问题。
一个遵循 ECMAScript 标准的代理(浏览器或 JS 引擎)也必须遵循事件循环机制。
事件循环是由一个或以上的 任务队列 组成的。
任务队列
任务队列(Task Queues),是一组任务的集合(Sets)。由于 JavaScript 是 单线程 语言,所以在 JS 中所有的任务都需要排队执行,这些任务共同组成了 任务队列,依次排队执行的过程,形成一个 执行栈(Execution Context Stack)。
在任务队列中最先执行是同步任务,这个就是按代码循序从上到下执行(本文不讨论关于变量提升之类的问题)。本文主要讨论异步任务的执行在任务队列里的执行情况。
异步任务
异步任务(Asynchronous Task)是需要等待被通知才以执行的任务。也就是说,它们不会直接进入主线程执行,而是进入到微任务队列或下一次事件循环中的任务队列进行等待。异步任务被分为宏任务和微任务来拆分不同的执行时刻和返回时刻。
宏任务
- 主代码块:JavaScript中的主线程代码。
- setTimeout和setInterval:定时器任务。
- I/O操作:例如文件读写、网络请求等。
- UI渲染:浏览器需要重绘或者重新布局的任务,包括 DOM 解析、CSS 解析、页面布局和绘制等与页面渲染相关的任务。。
- 用户交互事件:例如点击、滚动、输入等用户操作触发的事件。
- requestAnimationFrame:用于执行动画效果的任务。
微任务
- Promise回调函数:Promise对象的处理程序(then、catch、finally)。
- MutationObserver:监测DOM变化的任务。
- process.nextTick(Node.js环境下):在当前"执行栈"结束后立即执行的任务。
- queueMicrotask():用于将一个微任务添加到微任务队列中。
上面这些就只能靠死记硬背了
宏任务与微任务的执行顺序
在事件循环(Event Loop)中,当主线程空闲时,会从宏任务队列中选择一个任务进行执行。当一个宏任务执行完毕后,会检查是否有微任务队列,如果有,则将微任务队列中的所有任务依次执行完毕,然后再继续选择下一个宏任务执行。这样的过程循环进行,形成了事件循环。
总结来说,宏任务代表着较大粒度的任务,而微任务代表着较小粒度的任务。微任务通常在宏任务执行完毕后立即执行,因此微任务具有更高的优先级,可以在页面渲染前执行,从而提供更好的用户体验。
好,现在我们再回到题目本身
- 首先将代码宏任务和微任务分好,遇到Promise本身块里的属于宏任务。Promise.then放入微任务队列。(打印1,3)
- 遇到settimeout宏任务,但是延时了,所以要等微任务执行完才执行。
- 遇到nextTick,放入微任务队列。
- 遇到console.log(),宏任务直接打印。(打印8)
- 此时主线程空闲,接下来就是先执行微任务队列里的,首先是Promise.then。(打印2)
- 然后是nextTick,至此微任务执行完毕。(打印7)
- 微任务执行完毕后,延时的宏任务settimeout开始执行,遇到console.log,宏任务直接打印。(打印4)
- 遇到nextTick,放入微任务队列。
- 遇到console.log,宏任务直接打印。(打印6)
- 此时主线程空闲,微任务队列里还有个nextTick,直接打印。执行完毕。(打印5)
图文的等有空闲再上传。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律