最佳答案
首先,两个图表都是正确的,尽管第一个图表有些过时。 Node.js的异步部分过去由libev,libeio和libuv组成。但是,随着libuv在过去几年中的发展,“[in] the node-v0.9.0 version of libuv libev was removed”的发展使libuv负责Node.js的整个异步I/O流程(因此当然包括事件循环)。因此,现代版本的Node.js架构将用“libuv”替换“libeio”和“libev”(如第二幅图所示)。
这两张图在结构上不同的原因是,它们针对不同的角度进行了组织。图1表示从高层次到低层次的Node.js技术的不同分类(因此,这并不意味着工作流程);而图2是Node.js操作的实际工作流程。
举个比喻:假设您尝试使用图表表示汽车的不同零件。您可以通过多种方式执行此操作:您可以按照类别/功能来组织不同的片段(方案A),因此:
或者,您也可以按工作流程来组织作品(场景B):
(我不太了解汽车。零件的名称和实际的工作流程可能是错误的。列出它只是为了帮助理解。)
现在,由于组织作品的方式不同,因此它们出现的顺序也将有所不同。方案A与图1相似,方案B与图2相似。
我不确定您对Node.js的工作方式有多少了解,因此在继续解释它们彼此交互的方式之前,我将简要介绍一下适合Node.js架构的各个部分:
现在,第一个图应该有意义:最上面是用JavaScript编写的应用程序(模块和Node.js核心内置模块);底部是用C/C++编写的Node.js内部组件。要桥接它们以便它们可以通信,您需要绑定(bind)。这就是Node.js绑定(bind)所在的位置:在高级应用程序和低级Node组件之间。此图不一定代表工作流程;根据它们之间的关系/功能,这只是不同Node.js片段的分类。
第二张图表示Node.js应用程序的实际工作流程。应用程序中编写的代码由V8编译。该代码通过绑定(bind)与低级Node.js组件进行通信。用代码编写的所有事件都已向Node.js注册。触发事件后,将根据触发的顺序将它们排队在事件队列中。只要事件队列中仍然有剩余事件,事件循环就会继续拾取它们,调用它们的回调函数,然后将它们发送给工作线程进行处理。一旦执行了回调函数,其回调将再次发送到事件队列,等待再次被事件循环接收。
您的部分困惑可能来自第二张图表中使用的技术术语的选择。如果仔细看,在“NODE.JS BINDINGS”下面说“(NODE API)”,不幸的是,这是两件事。 Node.js API是其内置库的接口(interface),而从软件编程的角度来看,bindings是使用不同语言编写的代码之间的桥梁。
我希望这有帮助。
Node.js内部结构的更准确表示是:
(我前一段时间从互联网上的图片下载了这张图片,但我忘记了它的来源。如果图片属于您,请发表评论,我会在下面加点赞!谢谢!)
编辑:
我最近写了一篇更全面的文章,以一个易于理解的类比解释Node.js's architecture。希望对您有所帮助!
关于javascript - 哪个是正确的Node.js架构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36766696/