请解释非阻塞 I/O 的概念,并阐述 Node.js 实现非阻塞 I/O 的机制。
考察说明
考察对非阻塞 I/O 概念的理解及 Node.js 事件驱动机制的掌握程度。
回答思路
- 【回答框架 1】非阻塞 I/O 是指在发起 I/O 操作后,调用线程不会等待操作完成,而是立即返回,继续执行其他任务。当 I/O 操作完成时,通过回调、事件或轮询等方式通知调用者。
- 【回答框架 2】Node.js 基于事件循环(Event Loop)实现非阻塞 I/O。核心组件包括事件循环、线程池(libuv 提供)、事件队列。对于文件系统、网络等 I/O 操作,Node.js 会将其委托给底层异步接口或线程池处理。
- 【回答框架 3】以文件读取为例,调用 fs.readFile 时,Node.js 不会阻塞主线程,而是将读取任务交给 libuv 的线程池,主线程继续处理其他任务。读取完成后,回调函数会被放入事件队列,事件循环在合适的时机执行该回调。
- 【回答框架 4】事件循环的不同阶段(如 timers、poll、check 等)负责处理不同类型的回调,确保异步任务的执行顺序。Node.js 自身的 JavaScript 是单线程的,但 I/O 操作可以并行执行。
- 【回答框架 5】非阻塞 I/O 提高了并发处理能力和资源利用率,但增加了编程复杂性,如回调地狱。现代 Node.js 通过 Promise、async/await 等改进异步编程体验。
- 【关键点 1】非阻塞 I/O 是操作发起后立即返回,通过回调或事件通知完成。
- 【关键点 2】Node.js 通过事件循环和 libuv 线程池实现非阻塞 I/O。
- 【关键点 3】主线程不阻塞,I/O 操作并行执行,完成后回调进入事件队列。
- 【关键点 4】每个阶段处理不同类型的回调,决定执行顺序。
- 【关键点 5】异步编程可用 Promise、async/await 优化。
- 【易错点 1】不要把非阻塞 I/O 等同于并行执行,JS 主线程仍是单线程。
- 【易错点 2】事件循环的阻塞会导致所有异步任务延迟。
- 【易错点 3】大量 CPU 密集型任务会阻塞主线程,应使用 worker_threads 等。