JS 编程:带大家理解下事件中的循环机制、宏任务和微任务 - Web前端
作者:98wpeu发布时间:2026-10-24分类:网页前端技术浏览:3

执行顺序如下:
同步任务:进入主线程后,立即执行。
异步任务:会先进入 event table;等时间到了之后,再进入 任务队列 (Event Queue)排队(排队是因为同一时间,JS 只能执行一个任务),先进先出。比如说,
setTimeout(()=> {}, 1000)这种定时器任务,需要等一秒之后再进入 Event Queue。当主线程的任务执行完毕之后,此时主线程处于空闲状态,于是会去读取 Event Queue 中的任务队列,如果有任务,则进入到主线程去执行。
node.js 事件循环机制
浏览器的 EventLoop 依据的是 html5 规范。而 Node.js 的 EventLoop 是由node.js底层的 libuv 规定的。 libuv是一个专注于异步IO的跨平台库。
Node.js的事件循环中,有六个队列。其中,微任务有两个队列,宏任务有四个队列。
一、微任务队列:
顺序1:next tick queue。比如:PRocess.nextTick
顺序2:other queue。比如:Promise的then回调、queuemicrotask
二、宏任务队列:
顺序3:timer queue。比如:settimeout、SetInterval
顺序4:poll queue。比如:IO事件
顺序5:check queue。比如:setImmediate
顺序6:close queue。比如:close事件
宏任务和微任务
JS中的任务分为同步任务、异步任务。
JS中的异步任务分为宏任务(Macrotask)、微任务(microtask)。在早期,异步任务中只有宏任务,没有微任务。后来的语言标准中,推出了“微任务”,因为希望微任务能够尽早执行。
宏任务、微任务分类
事件循环的队列中,有两个队列。
1、宏任务队列,包含这些任务:
Ajax 网络请求
setTimeout、setInterval
DOM事件
UI渲染
I/O文件读写操作。
2、微任务队列,包含这些任务:
promise的then回调
Mutation Observer API:监听Dom节点变化。
queueMicrotask():可直接将某个任务加入到微任务队列中。
在执行一个 Promise 对象时,当走完 resolve() 进入 fulfilled状态后,会立刻把 .then()里面的代码加入到微任务队列当中。
任务的执行顺序
JS中的任务执行顺序:同步任务 --> 微任务 --> 宏任务。
在执行任何一个宏任务之前(不是队列,是一个宏任务),都会先查询微任务队列中是否还有任务需要执行:
当前宏任务执行之前,必须要保证微任务队列是空的。
如果微任务队列不为空,那就优先执行微任务队列中的任务。
任务执行顺序的面试题
实际开发中,基本不会出现下面这些题目,因为很多时候我们无法精准控制异步任务的执行顺序。但是它们在面试中出现的频率特别高,因为熟悉这些思维训练,有利于考察我们对JS单线程、事件循环机制、宏任务和微任务等原理的掌握程度。
题 1:宏任务和微任务的执行顺序
setTimeout(() => {
// 宏任务
console.log('setTimeout');
}, 0);
new Promise((resolve, reject) => {
resolve();
console.log('promise1'); // 同步任务
}).then((res) => {
// 微任务
console.log('promise then');
});
console.log('同步任务'); // 同步任务打印结果:
promise1 同步任务 promise then setTimeout
上方代码执行的顺序依次是:同步任务 --> 微任务 --> 宏任务。
题 2:在宏任务中嵌套了微任务
new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
console.log('setTimeout'); // 宏任务
}, 0);
console.log('promise1');
}).then((res) => {
// 微任务
console.log('promise then');
});
console.log('同步任务');结果:
promise1 同步任务 setTimeout promise then
上方代码解释:在执行宏任务的过程中,创建了一个微任务。但是需要先把当前这个宏任务执行完,再去创建并执行微任务。
题3:综合题
console.log("script start")
setTimeout(() => {
console.log("setTimeout1");
new Promise(resolve => {
resolve();
}).then(() => {
new Promise(resolve => {
resolve();
}).then(() => {
console.log("then1");
});
console.log("then2");
});
});
new Promise(resolve => {
// 下面这两行代码,即便调换顺序,也不影响打印结果
console.log("promise1");
resolve();
}).then(() => {
console.log("then3");
});
setTimeout(() => {
console.log("setTimeout2");
});
console.log('同步代码');
queueMicrotask(() => {
console.log("queueMicrotask")
});
new Promise(resolve => {
resolve();
}).then(() => {
console.log("then4");
});
console.log("script end");结果:
// 第一次循环 script start promise1 同步代码 script end // 第二次循环 then3 queueMicrotask then4 // 第三次循环 setTimeout1 then2 then1 // 第四次循环 setTimeout2
题4:async Await 题目
代码举例:
console.log('script start')
Async function async2() {
console.log('async2')
}
async function async1() {
console.log('async1 start')
await async2();
console.log('async1 end')
}
setTimeout(() => {
console.log('setTimeout')
}, 0)
async1();
new Promise(resolve => {
console.log('promise1')
resolve();
}).then(function () {
console.log('then1')
})
console.log('script end');结果:
script start async1 start async2 promise1 script end async1 end then1 setTimeout
相关推荐
- 加速网页索引及其 SEO 效果的 10 种方法 - Web前端
- Google 如何定义索引的优质内容 - Web前端
- 如何将 EEAT 应用于您的网站并提升页面 SEO? - Web前端
- Google EEAT:我们应该搜索具有高反向链接配置文件的其他文章吗? - Web前端
- 如何在项目中高效运用react-router-dom和yarn? - Web前端
- 如何在现有 React 项目中添加 TypeScript - Web前端
- 如何使用易于使用的虚拟机在 Linux 桌面上进行开发? - Web前端
- 关于Vue 3 Vite Setup,你需要知道的那些事儿 - Web前端
- 用实例解析关于 vue3 setup store 的用法 - Web前端
- Vue 3.4项目必须用npm吗?其他包管理工具能替代吗? - Web前端
- 网页前端技术排行
-
- 1[Web前端]用javascript实现默认图片替代未显示的图片 - Web前端
- 2分析Iconfont-阿里巴巴矢量常用图标库 - Web前端
- 3jQuery实例教程:制作网页中可折叠的面板 - Web前端
- 4【第六章】Foundation之按钮和下拉功能 - Web前端
- 5基于jquery的滚动条滚动固定div(附演示下载) - Web前端
- 6分享精心挑选的12款优秀jQuery Ajax分页插件和教程 - Web前端
- 7jQuery实现鼠标移到元素上动态提示消息框效果 - Web前端
- 8在Mac/PC上远程调试iPhone/iPad上的网页 - Web前端
- 9jQuery编写widget的一些技巧分享 - Web前端
- 最近发表
-
- WordPress随机显示特色图片插件:Random Post Thumbnails
- KeePass实现Chrome浏览器自动填充密码方法一
- LNMP一键包nginx 301强制跳转到https教程
- KeePass实现Chrome浏览器自动填充密码方法二
- #建站# 免费的VPS管理软件Xshell8/Xftp8中文版下载
- 使用Xshell 8连接VPS教程_电脑登录vps的方法
- WordPress评论界面添加烟花????效果
- 不同浏览器书签同步方案:坚果云+Floccus_详细使用教程
- iOS端KeePassXC客户端APP:Strongbox Password Safe
- 给WordPress评论中的Gravatar头像图片添加ALT属性


