如何在Node.js中解释和执行asynchronousJavaScript?

最近我对Node.js的核心进行了大量的研究,并对Node平台的内部工作有一些疑问。 据我所知,Node.js是这样工作的:

在这里输入图像描述

Node有一个使用Javascript编写的API,它允许程序员与文件系统和networking等进行交互。 但是,所有这些function实际上都是由C / C ++代码完成的,也是Node的一部分。 这是事情变得有点模糊的地方。 因此,Chrome V8引擎的工作基本上是将JavaScript编译成机器码。 V8是用C ++编写的,Javascript语言本身是由ECMA指定的,所以这些语言的关键字和特征等都是由它们定义的。 这导致我的第一个问题:

  1. 节点标准库如何能够与节点绑定进行交互,因为节点绑定是用C ++编写的?

  2. Chrome V8引擎如何在Node上下文中解释Javascript? 我知道它使用了一种叫做JIT的技术,在一个类似的问题中提到过:( https://softwareengineering.stackexchange.com/questions/291230/how-does-chrome-v8-work-and-why-was-javascript-但是这并不能解释Javascript是如何在Node上下文中解释的。 随同Node附带的Chrome V8引擎是否在Chrome浏览器上运行完全相同的引擎,还是已经修改为与Node一起使用?

这使我想到我的下一个问题。 所以Node提供了事件驱动的非阻塞IO。 它通过事件循环来完成这个事件,虽然它通常被称为“节点事件循环”,但它实际上是libuv库的一部分,libuv库是一个用来提供asynchronousIO的C ++库。 在高层次上,事件循环基本上是通过callback来访问的,这是一个原生的Javascript特性,也是Javascript被选为Node项目语言的原因之一。 以下是事件循环如何工作的示例:

在这里输入图像描述

这也可以通过这个整洁的小网站来演示: http : //latentflip.com/loupe/假设我们的Node应用程序需要调用外部API。 所以我们写这个:

request(..., function eyeOfTheTiger() { console.log("Rising up to the challenge of our rival"); }); 

我们的request调用被压入调用堆栈,并且我们的callback被传递到某个地方,直到请求操作结束。 当它发生时,callback被传递到callback队列中。 每次清除调用堆栈时,事件循环都会将callback队列顶部的项目压入调用堆栈,并在其中执行。 这个事件循环在一个线程上运行。 出现问题的时候是有人写'阻塞'的代码,或者从不离开调用堆栈的代码,并且有效地绑定线程。 如果总是有代码在调用堆栈上执行,那么事件循环将永远不会从callback队列中将项目推送到调用堆栈上,并且它们永远不会被执行,从而实质上冻结了应用程序。 这导致我到我的下一个问题:

  1. 如果JavaScript是由Chrome V8引擎解释的,而不是“控制”将代码推送到callback队列? Javascript代码如何由libuv事件循环处理?

我发现这个图像是一个演示过程:

在这里输入图像描述

这是我不确定Chrome V8引擎和libuv是如何交互的。 我倾向于认为节点绑定促进了这种交互,但我不太确定如何。 在上面的图片中,看起来好像NodeJS绑定只与V8下的JavaScript编译的机器代码交互。 如果是这样的话,比起我对V8引擎是如何解释Javascript的方式感到困惑的,NodeBindings可以区分callback和实际代码来立即执行。

我知道这是一个非常复杂而深刻的一系列问题,但是我相信这将有助于为理解Node.js的人们清理很多困惑,同时也帮助程序员理解事件驱动的优缺点,非阻塞IO在更基础的层面。

状态更新:刚刚从Sencha会议上观看了精彩的演讲( 链接在这里 )。 所以在这个演讲中,演讲者提到了V8embedded式指南( 链接在这里 ),并讨论了如何将C ++函数暴露给Javascript,反之亦然。 从本质上来说,它的工作原理是C ++函数可以暴露给V8,并指定如何将这些对象暴露给Javascript,V8解释器将能够识别你的embedded式C ++函数,并在它find与你指定的。 例如,可以将variables和函数暴露给实际用C ++编写的V8。 这实际上是Node.js的function; 它可以添加像Javascript这样的function,当它们被调用时,实际执行C ++代码。 这个清除了第1个问题,但是它并没有完全显示出Node标准库如何与V8一起工作。 关于libuv如何与其中任何一个进行交互,目前还不清楚。

基本上你在找什么是V8模板 。 它将所有的C ++代码公开为可以从V8虚拟机内调用的JavaScript函数。 您可以在调用函数或访问特定对象属性(读取访问拦截器 )时关联C ++callback。

我发现了一篇很好的文章,解释了所有这些 – NodeJS是如何工作的? 。 它还解释了libuv如何与Node协同工作来实现asynchronous性。

希望这可以帮助!