第 6 卷
23└─────────────┬─────────────┘ 24│
25┌─────────────▼─────────────┐
| 26 | │阶段4:poll(轮询) | │核心阶段,处理I/O回调(文件/网络请求),阻塞等待新任务 |
|---|---|---|
| 27 | └─────────────┬─────────────┘ | |
| 28 | │ | |
| 29 | ┌─────────────▼─────────────┐ | |
| 30 | │阶段5:check(检查) | │执行setImmediate()的回调 |
| 31 | └─────────────┬─────────────┘ | |
| 32 | │ | |
| 33 | ┌─────────────▼─────────────┐ | |
| 34 | │阶段6:close callbacks | │执行关闭回调(如socket.on('close')) |
| 35 | └───────────────────────────┘ |
✅ 2. 微任务的优先级和执行时机不同
浏览器:微任务队列只有1个,执行栈为空时一次性全清空。
Node.js:微任务分2类,优先级从高到低:
1.process.nextTick():独立的nextTick队列,优先级最高,任何阶段执行完后,先清空调 nextTick队列,再清空微任务队列;
- 普通微任务队列:Promise.then/MutationObserver/queueMicrotask(),优先级次之。
注:Node.js 11+ 版本优化了执行时机,每个宏任务执行完后,立即执行微任务队列(与浏览器一致);Node.js 10- 版本是整个阶段的宏任务执行完后,再执行微任务队列。
✅ 3. 宏任务的类型和优先级不同
浏览器宏任务优先级(大致):
script整体执行 > DOMContentLoaded > setTimeout/setInterval > AJAX/fetch > load > requestAnimationFrame。
Node.js宏任务优先级(按阶段顺序):
timers(setTimeout) > pending callbacks > poll(I/O) > check (setImmediate) > close callbacks。
✅ 4. 页面渲染的差异
- 浏览器事件循环:每轮循环都会触发页面渲染,是核心环节,保证页面可视化更新;
• Node.js事件循环:无页面渲染环节,Node.js是服务端运行环境,无需渲染页面,专注于I/O处
✅ 5. 异步API的支持差异
• 浏览器:支持DOM事件、AJAX、requestAnimationFrame、MutationObserver等前端专属异步
API;
• Node.js:支持文件I/O、网络I/O、child_process、setImmediate、process.nextTick等服务端专
属异步API,无DOM相关API。
✅ 6. 任务队列的数量差异
- 浏览器:仅1个宏任务队列 + 1个微任务队列;
- Node.js:6个宏任务队列(对应6个阶段) + 2个微任务队列(nextTick + 普通微任务)。
✅ 核心差异总结表
| 维度 | 浏览器事件循环 | Node.js事件循环 |
|---|---|---|
| 阶段划分 | 无明确阶段,仅分2个队列 | 6个明确执行阶段,按顺序执 |
行
| 微任务执行 | 执行栈空→全清微任务→执行 | 每个宏任务执行完→清 |
|---|---|---|
| 1个宏任务 | nextTick→清微任务 | |
| 渲染环节 | 必含,每轮循环触发 | 无,服务端无渲染需求 |
| 宏任务优先级 | 无严格顺序,按添加时间执行 | 按阶段顺序执行,优先级固定 |
| 异步API | 前端专属 | 服务端专属 |
| (DOM/AJAX/RAF) | (I/O/setImmediate) | |
| 核心目标 | 保证页面交互流畅,非阻塞渲 | 高效处理I/O请求,高并发服 |
| 染 | 务 |
17. 描述process.nextTick在Nodejs事件循环中的执行顺序及其与微任务
的关系
process.nextTick的定义
process.nextTick() 是Node.js专属的微任务API,用于将回调函数添加到nextTick专属队列,是Node.js中优先级最高的异步任务,独立于普通微任务队列。
空为止);
2.nextTick队列清空后,再执行普通微任务队列(Promise.then/MutationObserver等)的所有回调;
- 微任务队列清空后,才会执行Node.js事件循环的各个阶段的宏任务;
- 任何阶段执行完一个宏任务后,都会先清空调nextTick队列→再清微任务队列→再执行下一个宏任
务;
- 若在 process.nextTick() 中再次调用 process.nextTick(),新的回调会加入当前
nextTick队列末尾,立即执行,不会进入下一轮循环(可能导致事件循环阻塞)。
process.nextTick与普通微任务的关系
- 1. 同属微任务,process.nextTick优先级更高(核心关系)
- 微任务分为两级: nextTick队列(一级微任务) > 普通微任务队列(二级微任务);
- 执行顺序:同步任务 → process.nextTick()全清 → 普通微任务全清 → 宏任务。
- 2. 执行机制一致,均为批量执行
- 两者都是队列式存储,遵循「先进先出」;
- 执行时都会一次性清空当前队列,队列中产生的新任务会加入末尾,同步执行。
- 3. 所属队列不同,相互独立
• process.nextTick():存入nextTickQueue(专属队列,由Node.js底层维护,效率更
高);
- 普通微任务:存入microtaskQueue(标准微任务队列,遵循ES6规范)。
执行顺序示例(直观理解)
Code block
1console.log('同步任务1'); // 1. 同步任务,立即执行 2
| 3 | Promise.resolve().then(() => {//普通微任务 |
|---|---|
| 4 | console.log('普通微任务Promise');// 4.执行普通微任务 |
| 5 | }); |
| 7 | process.nextTick(() => {// nextTick微任务 |
| 8 | console.log('nextTick1');// 2.执行nextTick |
全站分卷索引 · 10 卷
- 1第 1 卷
- 2第 2 卷
- ◦ 处理样式优先级(!important > 行内样式 > ID选择器 > 类/伪类/属性选择器 > 标签/伪元素选择
- 关键特性
- 6. 详述浏览器加载和执行JavaScript文件的机制
- JS加载执行核心机制(单线程+阻塞特性)
- • 浏览器解析HTML时,遇到 <script> 标签,立即暂停后续HTML解析,发起HTTP请求加载JS文
- • 可通过属性优化加载:
- ◦ async:异步加载,加载完成后立即执行(执行顺序不确定,不阻塞HTML解析,阻塞渲
- ◦ defer:异步加载,HTML解析完成后、DOMContentLoaded事件前执行(执行顺序与标签
- ◦ type="module":ES6模块加载,默认异步,遵循 defer 规则,支持按需加载、作用域隔
- • V8引擎采用即时编译(JIT):将AST转换为字节码,再将热点代码(频繁执行)编译为机器码,
- 关键特性
- • 异步JS(async/defer/module)仅解除对HTML解析的阻塞,仍会阻塞 DOMContentLoaded 事
- 3第 3 卷
- 4第 4 卷
- 5第 5 卷
- 6第 6 卷
- ✅ 2. 微任务的优先级和执行时机不同
- ✅ 3. 宏任务的类型和优先级不同
- ✅ 4. 页面渲染的差异
- • Node.js事件循环:无页面渲染环节,Node.js是服务端运行环境,无需渲染页面,专注于I/O处
- ✅ 5. 异步API的支持差异
- • 浏览器:支持DOM事件、AJAX、requestAnimationFrame、MutationObserver等前端专属异步
- • Node.js:支持文件I/O、网络I/O、child_process、setImmediate、process.nextTick等服务端专
- ✅ 6. 任务队列的数量差异
- ✅ 核心差异总结表
- 17. 描述process.nextTick在Nodejs事件循环中的执行顺序及其与微任务
- 的关系
- process.nextTick的定义
- 7第 7 卷
- 8第 8 卷
- 9第 9 卷
- 10第 10 卷
- • 不再使用的全局变量,手动置空释放:`window.data = null`(浏览器)、`delete global.data`
- • 避免闭包长期引用大对象,若必须引用,业务结束后手动清空闭包引用:`persistentClosure =
- • DOM元素移除前,通过`removeEventListener`移除对应的事件监听(注意:监听函数必须与绑
- • 组件生命周期销毁时(如React的`componentWillUnmount`、Vue的`beforeUnmount`),批
- • 定时器/计时器使用后,务必通过`clearTimeout`/`clearInterval`清理,尤其是在组件销毁、页
- • 将定时器ID存储在实例属性中,便于后续清理:`this.timer = setTimeout(...)`,销毁时执行
- • 避免在JS中长期缓存DOM元素,优先通过`document.querySelector`动态获取,减少不必要的
- • 异步任务(Promise/AJAX)确保完成:无论成功/失败,都调用`resolve/reject`;使用
- • 内存缓存设置上限和过期机制:使用`lru-cache`等成熟缓存库(自动淘汰最近最少使用的缓
- • 优先使用`WeakMap/WeakSet`作为缓存:它们的键是弱引用,当键对应的对象无其他引用时,会
- • 浏览器端:使用Chrome开发者工具(Memory面板),通过HeapSnapshot(堆快照)对比内存
- • Node.js端:使用`--inspect`参数启动服务,通过Chrome开发者工具调试;使用`clinic.js`、