本文从对线程、事件循环、事件循环常见的问题和错误上分别进行说明,进一步探索了 Node 的核心工做原理。
每当人们谈论 Node.js 时,都会出现不少问题,好比它到底是什么、这项技术有什么用、它是否有将来等等。node
让咱们尝试讨论第一部分。回答这个问题最简单的方法是列出 Node 在技术上的许多定义,如:可是,这些答案并不能令我彻底满意,由于缺乏一些东西。在阅读上面的要点后,你可能会认为 Node.js 只是另外一种 JavaScript 技术,但理解它最重要的方法是分析它是如何实现异步并具备彻底非阻塞 I/O 系统的。npm
这才是为何它能成为每一个 Web 开发人员必备之物的真正缘由。异步
准确了解 Node 如何在幕后工做不只能增进对这项技术的更多了解,并且还会吸引那些还未用过它的人认识并开始学习它。ide
而对于那些已是该领域专业人士的人来讲,了解 Node 的内部和外部将使你成为一名最新和最前沿的开发人员,而且可以根据自身的需求提升 Node 的性能。函数
所以,为了深刻了解 Node ,咱们将解析其核心部分——事件循环的工做机制。事实上,事件循环就是负责 Node 非阻塞 I/O 模型的部分。工具
刷新对线程的认知在深刻了解事件循环以前,我想花些时间在线程上。若是你想知道为何这很必要,我会告诉你,为了更好地理解一个概念,咱们必须首先开始在脑海中造成一个词汇表,它将有助于咱们识别系统的每一个部分。这样,在稍后阅读有关事件循环、事件循环如何工做以及线程的概念如何应用在事件循环中的内容时,你才会有很大的优点。oop
每当咱们运行一个程序时,咱们都会建立一个它的实例,而且咱们会调用一些内部线程,他们是与该实例相关联的。线程能够看做是 CPU 必须执行的操做单元。许多不一样的线程能够与程序的单个进程相关联。如下是一个图形,它能够帮助你在脑海中造成这个概念:性能
线程的简单图形学习
在谈论线程时,最重要的一点是 :计算机在某个时刻应该处理哪一个线程?优化
众所周知,咱们的机器资源(CPU、RAM)是有限的,所以正确分配资源很是重要,或者说,哪些操做应该优先执行。这一切都必须实现,并且同时,须要确保全部操做不能耗费太多时间,由于没有人喜欢笔记本电脑速度过慢。
用于解决资源分配问题的机制就叫做调度,它由咱们的操做系统中称为 OS 调度程序的实体来管理。这背后的逻辑可能很是复杂,但总而言之,咱们能够将执行此操做的两大方法组合在一块儿:多核机器: 为不一样的核分配不一样的线程。
多核机器如何处理线程
使用优化逻辑,以减小死锁时间:这是对咱们来讲最切实的方法。若是咱们仔细研究一下线程是如何工做的,咱们将看到操做系统调度器能够识别出CPU在什么时候等待其余资源来执行一个做业,所以它能够被分配来同时执行其余操做。这一般发生在很是繁重的 I/O 操做上,例如硬盘读取。
如今咱们已经对线程的工做原理有了新的了解,咱们终于能够解决Node.js 事件循环逻辑了。经过阅读本文,你会了解前面的解释它背后的缘由,并且每一个部分都会自行找到正确的位置。
每当咱们运行 Node 程序时,都会自动建立一个线程。这个线程就是咱们整个代码库被执行的惟一地方。其中,还生成了一个称为事件循环的东西。这个循环的做用是安排咱们惟一的线程在某个给定的时间点应该执行哪些操做。
请注意:在咱们运行程序后那一刹那,事件循环不会马上生成。实际上,只有在整个程序执行完毕后事件循环才会运行。
详情如今让咱们尝试模拟事件循环的工做原理以及它如何使咱们的程序开始工做。为此,我将伪装本身正在使用一个名为 myProgram 的文件为 Node 提供信息,而后咱们再详细了解事件循环将执行的全部操做。
特别的,我将首先编写一个简短的图形解释,来讲明在某个事件循环 tick 过程当中发生了什么,而后我将以更深刻的方式探讨这些阶段。
事件循环的图形说明
第1步:performChecks
我不该该告诉你事件循环其实是一个循环。这意味着它有一个特定的条件,这个条件将决定循环是否须要再次迭代。事件循环的每次迭代都称为 tick。
事件循环执行 tick 的条件是什么?
每当咱们执行程序时,咱们都会有一系列须要执行的操做。这些操做可分为三个大类:
咱们稍后会详细介绍这些内容;如今,让咱们记住,只要其中一个操做处于挂起状态,事件循环就会执行一个新的 tick。
第2步:执行 tick
对于每一个循环迭代,咱们能够将其分为如下阶段:setImmediate()
函数相关)相关的任何函数。阶段 5:管理关闭事件,用于清理应用程序的状态。
这是对这项技术的一种很是广泛的误解。虽然 Node 是在单个线程上运行,可是 Node.js 标准库中包含的有些函数并非如此(例如 fs 模块函数);它们的逻辑运行在 Node.js 单线程以外,这样作是为了保持程序的速度和性能。
这些其余线程在哪里外包?使用 Node.js 时,会使用一个名为 libuv 的特殊库模块来执行异步操做。此库还与 Node 的后向逻辑一块儿被用来管理称为 libuv 线程池 的特殊线程池。
此线程池由四个线程组成,它们负责委派对事件循环来讲太繁重的操做。
那么事件循环是一种相似堆栈的结构吗?从这个意义上说,虽然在上述过程当中涉及到了一些相似堆栈的结构,但更准确的答案是事件循环由一系列阶段组成,每一个阶段都有本身的特定任务,并且全部阶段都以循环重复的方式被处理。有关事件循环的更多信息,请看这个对话: https://www.youtube.com/watch?v=PNa9OMajw9w。
结论了解事件循环是使用 Node.js 的重要部分,不管你是想得到有关此技术更多看法、了解如何提升其性能,仍是但愿找到学习一个新工具的理由,本文都会对你有所帮助。
英文原文: https://blog.logrocket.com/a-complete-guide-to-the-node-js-event-loop/