Node.js 事件循环详解

Node.js 使用单线程。你可能会好奇它是如何同时处理成千上万个请求的。

秘诀就在于事件循环 (Event Loop)。

Node.js 不会等待任务完成,而是将耗时任务交给操作系统处理。它会继续执行下一个任务。这使得你的应用程序运行快速且响应迅速。

阻塞 vs 非阻塞

如果你使用像 readFileSync 这样的同步函数,服务器就会停止工作。它会等待文件读取完成。其他用户无法获得响应。这会严重损害性能。

如果你使用 fs.readFile,服务器会继续运行。它会在后台读取文件的同时处理其他请求。

事件循环的工作原理

循环会经过几个阶段:

• Timers:处理 setTimeout 和 setInterval。 • Pending Callbacks:处理系统级错误。 • Poll:接收新连接并处理 I/O(如数据库查询)。 • Check:处理 setImmediate。 • Close Callbacks:处理套接字 (socket) 关闭。

优先级顺序

并非所有任务都是平等的。Node.js 使用两个队列:

  1. Microtask Queue:存放 Promise。
  2. Callback Queue:存放 setTimeout 和 I/O。

Microtask Queue 总是优先执行。如果你同时有一个 Promise 和一个 setTimeout,Promise 会在定时器之前完成。

调用栈与队列

调用栈 (Call Stack) 追踪当前正在运行的代码。当一个任务完成时,它的回调函数会进入队列。事件循环会等待调用栈清空后,才从队列中提取任务。

避免这些错误:

• 不要使用死循环。这会导致整个应用卡死。 • 不要在生产环境中使用同步文件方法。 • 不要主线程上运行繁重的数学计算或视频处理。

对于繁重任务,请使用 Worker Threads 或后台作业。

总结

Node.js 之之所以快,是因为它从不等待。它将 I/O 任务委派出去,并使用事件循环来管理结果。这种架构允许单个线程为众多用户提供服务。

事件循环的哪个部分让你觉得最难学?在评论区告诉我吧。

来源:https://dev.to/synfinity-dynamics-pvt-ltd/nodejs-event-loop-explained-how-nodejs-handles-thousands-of-concurrent-requests-1heo