JS 事件循环、宏任务微任务:单线程底层原理 + 执行顺序

一、JS 为什么是单线程?

JS 最初设计用途是操作页面 DOM 。

如果 JS 是多线程,就会出现冲突场景:

线程 A 修改 DOM,线程 B 同时删除同一个 DOM,浏览器不知道以哪个操作为准,会引发混乱。

所以规定:JS 主线程只有一个,同一时间只能做一件事,所有 DOM 操作串行执行,避免 DOM 并发冲突。

补充:单线程 ≠ 浏览器只有一个线程。浏览器还有其他辅助线程:定时器线程、HTTP 请求线程、渲染线程,这些线程是浏览器提供的,不属于 JS 主线程。

二、什么是事件循环(Event Loop)

JS 单线程遇到异步任务的时候,不会阻塞等着,而是把异步任务交给浏览器其他线程去处理。

等异步任务满足触发条件后,回调函数会被放到对应的任务队列排队。

事件循环,就是主线程不断读取任务队列、取出任务执行的循环调度机制。

简单一句话:主线程干完手里同步代码,就去队列拿任务执行,周而复始,这个循环就是事件循环。

三、任务分类:宏任务、微任务

✅ 微任务(microtask)

优先级更高,在当前同步代码结束后立刻清空

常见:

  • Promise.then / Promise.catch / Promise.finally
  • MutationObserver(监听 DOM 变化)
  • queueMicrotask()

特点:微任务队列是一个先进先出队列,只要队列里还有微任务,就会一直执行完,才会往下走。

✅ 宏任务(macrotask)

优先级低于微任务

常见:

  • setTimeout、setInterval
  • AJAX 请求回调
  • script 标签整体代码(初始同步代码本身也是宏任务)
  • UI 渲染

特点:一次循环只拿一个宏任务执行,执行完之后,再去清空所有微任务。

四、核心执行顺序(重中之重)

  1. 先执行同步代码(主线程栈里面的代码)
  2. 同步栈清空 → 一次性清空全部微任务队列(所有微任务依次执行,如果微任务里面又产生新微任务,新微任务继续在本轮清空)
  3. 微任务队列为空 → 取一个宏任务执行
  4. 这个宏任务执行完毕后,回到第二步,再次清空微任务,循环往复

口诀:同步优先 → 清光微任务 → 一个宏任务 → 循环

执行流程图文字版:

同步代码栈 → 微任务队列(全部执行完)→ 取 1 个宏任务 → 微任务队列(全部执行完)→ 取下一个宏任务......

五、代码示例

复制代码
console.log('同步1');
setTimeout(()=>{
  console.log('宏任务 setTimeout')
},0)
Promise.resolve().then(()=>{
  console.log('微任务 promise')
})
console.log('同步2');

输出顺序:

复制代码
同步1
同步2
微任务 promise
宏任务 setTimeout

执行拆解:

  1. 打印同步 1
  2. setTimeout 交给定时器线程,回调放进宏队列
  3. Promise.then 回调放进微队列
  4. 打印同步 2,同步栈清空
  5. 清空微队列:打印 promise
  6. 微任务空了,取出宏任务:打印 setTimeout

六、容易踩坑的两点

  1. 在微任务执行过程中新增的微任务,依旧属于本轮微任务,会接着执行,不会丢到下一轮
  2. setTimeout 延时 0ms,不是立刻执行,只是尽快加入宏任务队列,必须等本轮微任务全部跑完才执行

总结

  • JS 单线程:为了防止多个线程同时操作 DOM 产生冲突;
  • 事件循环:JS 主线程调度异步回调的运行机制;
  • 顺序规则:同步代码 > 全部微任务 > 单个宏任务,不断循环。

结尾

事件循环是 JS 异步的根基,async/await 本质也是 Promise 语法糖,依旧遵循这套微宏任务规则。弄懂这个,面试异步题、排查异步顺序 bug 就稳很多。

相关推荐
其实防守也摸鱼1 小时前
Chrome 扩展安全攻防实录:从攻击面到防御实践
开发语言·前端·网络·chrome·安全·web安全·php
web打印社区1 小时前
Lodop排障总纲-常见报错一张表
开发语言·前端·javascript·chrome·websocket
程序员大阳2 小时前
副队长JavaScript教程(56)-DOM之表单操作
javascript·dom·表单操作
Dxy12393102162 小时前
JS AES加密详解
开发语言·javascript·ecmascript
信息安全失业大专人员2 小时前
每日了解一个智能体-WorkBuddy
开发语言·ai·c#·智能体
4ever.ov03 小时前
精学C++第一站 从命名空间到引用:C++入门核心语法全梳理(13000字长文)
开发语言·c++·clion
小杨互联网3 小时前
Go 现代 CLI 工具离线镜像合集
开发语言·后端·golang·开源·go·命令行
揽星河..3 小时前
【C语言】数组
c语言·开发语言·算法
FRing033 小时前
JavaScript入门到精通三十三(异常处理、call方法、apply方法、bind方法、防抖、节流)
开发语言·前端·javascript