面试题答案
一键面试相同点
- 基于单线程:浏览器和 Node.js 中的 JavaScript 都运行在单线程环境中,同一时间只能执行一个任务,避免了多线程编程中复杂的资源竞争和同步问题。
- 事件循环基础:都依赖事件循环机制来处理异步任务。事件循环不断检查调用栈是否为空,当调用栈为空时,从任务队列中取出任务放入调用栈执行。
不同点
- 任务队列分类
- 浏览器:任务队列分为宏任务队列(如
setTimeout
、setInterval
、script
(整体代码)、I/O
、UI rendering
等)和微任务队列(如Promise.then
、MutationObserver
等)。微任务在宏任务之间执行,且一个宏任务执行完后,会清空当前微任务队列再执行下一个宏任务。 - Node.js:在 Node.js v11.0.0 之前,微任务队列在每一个阶段(timers、I/O 等)之间执行;v11.0.0 之后,行为与浏览器基本一致,即宏任务执行完后,清空微任务队列再执行下一个宏任务。此外,Node.js 有更复杂的任务队列分类,如
timers
阶段处理setTimeout
和setInterval
,I/O callbacks
阶段处理大部分 I/O 回调等。
- 浏览器:任务队列分为宏任务队列(如
- 执行环境
- 浏览器:主要运行在客户端,侧重于处理用户界面交互、DOM 操作、网络请求等前端相关任务。
- Node.js:运行在服务器端,专注于处理服务器相关的任务,如文件系统操作、网络服务(HTTP 服务器等)。
对开发不同类型应用的影响
- 前端页面(浏览器环境)
- 影响:由于要处理用户交互和 UI 渲染,需要合理安排任务执行顺序。例如,如果在宏任务中执行大量计算,会阻塞 UI 渲染和用户交互,造成页面卡顿。微任务的执行时机使得一些需要及时反馈的异步操作(如 Promise 链式调用)可以在合适的时机执行,不影响页面流畅度。
- 应对策略:避免在主线程执行长时间的同步任务,将复杂计算放到 Web Worker 中并行处理。合理使用宏任务和微任务,对于需要立即执行且不阻塞 UI 的任务,可使用微任务;对于一些延迟执行或与 I/O 相关的任务,使用宏任务。
- 后端服务(Node.js 环境)
- 影响:Node.js 的事件循环机制使其能够高效处理大量并发的 I/O 操作,但如果在某个阶段(如
timers
或I/O callbacks
)执行了长时间的同步任务,会阻塞整个事件循环,影响其他请求的处理。不同阶段的任务执行顺序和特点需要开发者清楚了解,以优化性能。 - 应对策略:避免在关键阶段(如 I/O 处理阶段)执行同步阻塞代码。对于 CPU 密集型任务,可以使用
cluster
模块开启多进程并行处理,充分利用多核 CPU 资源。合理设置定时器和处理 I/O 回调,确保任务的高效调度。
- 影响:Node.js 的事件循环机制使其能够高效处理大量并发的 I/O 操作,但如果在某个阶段(如