JavaScript中的宏任务和微任务

面试中经常会被问到什么宏任务和微任务?工作中也会出一个奇怪的问题,两行代码,一会A结果现出来,一会B结果先出来,搞得一头雾水。有些人为了懒省事,全都是用async await,亦或者写个setTimeout,也不去追究原理,能解决问题就行。接下来就对这个问题展开讨论。

什么是宏任务和微任务?

宏任务是由宿主(浏览器、Node)发起的,一般在JavaScript引擎空闲时执行(不知道这样说合不合理)。常见的宏任务有:setTimeoutsetIntervalAjaxDOM事件

微任务是指在当前任务执行结束后立即执行的任务。常见的微任务有:Promiseasync/await。其中Promise本身是同步的,.then/.catch才是异步的。

执行顺序

首先,在JavaScript中,任务分为同步任务和异步任务,异步任务又有宏任务和微任务。同步任务在主线程中,异步任务会进入任务队列。

同步任务 》微任务 》宏任务

一起来看一下下面这个例子:

js 复制代码
console.log(1);
setTimeout(() => {
  console.log("setTimeout");
}, 1000);
new Promise((resolve, reject) => {
  console.log("Promise1");
  resolve("resolve");
  console.log("Promise2");
}).then((data) => {
  console.log(data);
});
console.log(2);

先区分一下都是什么任务:

按照上面的顺序,依次输出1Promise1Promise22resolvesetTimeout,这里值得说一下Promise本身是同步的,.then/.catch才是异步的,所以会先输出Promise1,而resolve("resolve")是告诉Promise成功了,并不阻碍进程,所以会继续输出Promise2

可能有人会说setTimeout一秒后才执行,肯定最后输出了,再看一个例子,把setTimeout设置为0,应该会立即执行吧?:

js 复制代码
console.log(1);
setTimeout(() => {
  console.log("setTimeout");
}, 1000);
setTimeout(() => {
  console.log("setTimeout0");
}, 0);
new Promise((resolve, reject) => {
  console.log("Promise1");
  resolve("resolve");
  console.log("Promise2");
}).then((data) => {
  console.log(data);
});
console.log(2);

也是先分析都是什么任务,依次输出1Promise1Promise22resolvesetTimeout0setTimeout,虽然setTimeout设置为0,他也是宏任务,按照执行顺序,也是要排队的。

再看一个例子:

js 复制代码
console.log(1);
setTimeout(() => {
  console.log("setTimeout");
}, 10);
console.log(2);
for (let index = 0; index < 10000; index++) {
  console.log(10000);
}

定时器设置10毫秒,下面循环10000次,肯定会超过10毫秒了,应该会先输出setTimeout了吧,实时并不是这样,因为for是同步的,但是JavaScript引擎一直在忙没空去搭理它。

总结

  • JavaScript中的任务分为同步任务和异步任务,异步任务又有宏任务和微任务;
  • JavaScript先查找同步任务,然后再去任务队列中查找微任务,最后才去任务队列中查找宏任务;
  • 执行顺序:同步任务 》微任务 》宏任务。
相关推荐
fangzhanpeng16811 小时前
(前端)2.js变量作用域样例
开发语言·前端·javascript
码艺-Alimjan13 小时前
Vue项目源码备份最佳实践:无视node_modules,打包体积仅2MB
前端·javascript·vue.js
xixiaoyunya14 小时前
JavaScript 异步编程全解析:从回调地狱到 async/await 的演进之路
开发语言·javascript·ecmascript
张元清15 小时前
React useScrollLock Hook:为弹窗锁住页面滚动 (2026)
javascript·react.js
Sayai15 小时前
【无标题】ECharts 实现日志量异常检测:基线 ±Kσ 基带 + 灵敏度切换(Vue2 实战)
前端·javascript·echarts
默_笙16 小时前
💌 为了把"主题色"传给孙子组件,我翻了五层楼——直到遇见了 useContext
前端·javascript
小KK_16 小时前
JS 事件循环从小白视角入门:宏任务、微任务与 async/await 一网打尽
前端·javascript
kisshyshy17 小时前
从 useRef 到 Web Worker:理解 React 可变对象与浏览器多线程
前端·javascript·react.js
执行部之龙20 小时前
AI 前端流式输出手写与扩展知识
前端·javascript·面试·agent
程序员老赵20 小时前
Docker 部署 ZLMediaKit:轻松搭建高性能流媒体服务平台
前端·javascript·后端