解释节点callback和单线程

节点的javascript环境是单线程的,还是一切发生在同一时间? 或者(更可能的是)这些语句都不能解释节点上正在发生的事情。

我是新来的节点,并试图了解它如何处理callback。 我在这个主题上的search并没有被certificate是有效的,似乎有多个受众使用像“线程,locking和单线程”这样的术语,为每个观众使用不同的上下文,而且我没有足够的经验来正确parsing节点我在读什么

从我读到的节点的JavaScript执行环境,就像浏览器的单线程。 也就是说,尽pipe一切都是围绕asynchronouscallback来devise的,但所有事情都是以确定性的顺序进行的,并且没有两个线程同时修改同一个variables或者运行语句。 我也读过这意味着节点程序员 – 用户不必担心locking语义。

如果我在浏览器的土地,并使用其中一个stream行的JavaScript库来build立一个非DOM事件处理程序的callback,像

console.log("Here"); $.each([1,2,3],function(){ console.log("-- inside the callback --"); }); console.log("There"); 

我的输出是一贯的

 Here -- inside the callback -- -- inside the callback -- -- inside the callback -- There 

但是,如果我使用节点js中的callback来执行此类操作(从命令行将其作为shell脚本运行)

 var function example() { var fs = require('fs'); console.log("Here"); fs.readdir('/path/to/folder', function(err_read, files){ console.log('-- inside the callback --'); }); console.log("There"); for(var i=0;i<10000;i++) { console.log('.'); } } example(); console.log("Reached Top"); 

我始终如一(看起来 – 看到“没有太多的经验”上面)得到这样的结果

 Here There . . (repeat 10,000 times) Reached Top -- inside the callback -- 

也就是说,节点在调用callback函数之前完成函数example

这是节点中的确定性行为吗? 或者在example函数完成之前有时候会调用callback函数? 还是会依赖于库中使用callback的实现?

我明白节点背后的想法是编写基于事件的代码 – 但我试图了解什么节点真的在做什么,哪些行为可以依赖,什么不可以。

在这种情况下,您正在调用正在执行IO的function并且是asynchronous的。 这就是为什么你看到你的方式输出。

因为其余的代码正在内联执行 – 在单个执行线程上,它是在IO事件有机会进入事件循环之前完成的。

我会说,期待这种行为,但不要绝对依靠它,因为它取决于使用callback函数库的实现。 一个(坏的,邪恶的)实现者可能正在做一个同步的请求,看是否有任何工作要做,如果没有,立即callback。 (希望你永远不会看到这个,但是…)。

节点的javascript环境是单线程的,还是一切发生在同一时间?

Node具有单线程的程序执行模式,这意味着在一个节点进程中,任何时候只能执行一条指令。 执行将继续,直到程序产生控制。 这可能发生在程序代码的末尾,或者当callback到达结束时。

在第一种情况下:

 console.log("Here"); $.each([1,2,3],function(){ console.log("-- inside the callback --"); }); console.log("There"); 

他们的关键是$.each 同步使用callback,所以有效地调用callback以确定性的顺序。

现在在第二种情况下, fs.readdir asynchronous使用callback – 它将等待事件的callback触发(即读取目录结束时)。 这可以随时发生。 但是,调用函数不会产生控件,所以在调用任何callback之前, example总是会完成。

一句话:函数/全局作用域的所有代码在该函数/全局作用域中定义的任何callback之前执行。

我想补充一点到@ dc5的答案。 在它的网站上,他们将节点描述为

Node.js使用事件驱动的非阻塞I / O模型

事件驱动部分非常重要。 当我无法理解节点程序的执行模型时,通常会清除我的疑惑。

举个例子,发生的事情是:

  1. 这里是打印到控制台。

  2. 对这些文件进行asynchronous调用。

  3. 节点将侦听器附加到asynchronous调用。

  4. 继续执行线,并打印。

现在可能是asynchronous调用在正在执行的当前代码片段之前完成,但是节点js完成了手头任务,然后返回服务于asynchronous调用。

所以不要等待任何事情继续执行。 这就是为什么节点js执行循环从不空闲的原因。