Node.js的行为差异内置事件和自定义事件的事件循环
我正在阅读关于node.js中的事件循环。 按照我在stackexchange中读过的各种文章和post,我得到所有的callback函数都附加在任务队列的末尾,执行完主文件之后,队列中的所有任务都按顺序执行 。 我试图通过一个小程序来确认它。 我发现了一个奇怪的行为。 以下是我创build的main.js文件的内容。
//Declare file open event handler var fs = require("fs"); var ws = fs.createWriteStream("C:\\test.txt"); ws.on("open", function(fd) { console.log("#Event file 'open'"); }); //Wait for 5 seconds var startTime = new Date().getTime(); console.log("Give time of 5 seconds to get file opened (being conservative)...\n"); while(new Date().getTime() - startTime < 5000) {} //Create custom event var util = require("util"); var EventEmitter = require("events").EventEmitter; var CustomEventEmitter = function() {}; util.inherits(CustomEventEmitter, EventEmitter); //Declare custom event handler var customInstance = new CustomEventEmitter(); customInstance.on("tick", function() { console.log("#Event custom 'tick'"); }); //Emit custom event customInstance.emit("tick"); console.log("#End 'main.js'");
它给了我以下输出:
Give time of 5 seconds to get file opened (being conservative)... #Event custom 'tick' #End 'main.js' #Event file 'open'
在“#End'main.js'”之后输出日志“#Event file”open'“,但是如果日志”#Event custom'tick'“被logging在任务队列中,那么该怎么办呢?
我的意思是内部事件如何显示正确的行为,而定制事件没有?
请纠正我的理解:)
关键是, emitter.emit()
是同步的。
这是发生了什么,一步一步:
-
当你调用
fs.createWriteStream()
时,调用一个asynchronous函数,在当前滴答结束之后,它被放入任务队列进行处理。 -
然后你的
while
循环会发生5秒,这对我们将会看到的事件发射顺序没有影响。 -
接下来你发出你的
tick
事件。 凉。emit()
是同步的,并触发侦听器,所以: #Event自定义“打勾”日志在这里 -
您的主要function结束。 #在此处结束“main.js”日志。
-
Node通过
createWriteStream()
将任务队列放置在任务队列中,最终导致open
事件触发,导致: #Event文件“打开”日志
所以这就是为什么事情顺序出现的原因。
当你像你一样遍历一个while循环时,你基本上劫持了线程,并把CPU挂起了5秒钟。 用setInterval或setTimeout尝试相同的testing。 SetTimeout / Interval将允许js引擎在循环之间执行其他任务。 即使你给它1毫秒的差距,这足以让引擎清除队列。
(进一步澄清 – 编辑)
Javascript会把callback放在堆栈的后面。 所以,如果你在一些例程中粘贴了大量的顺序语句,那么它们都必须在文件callback才能在行后面完成。
在你的自定义事件的情况下,这不是一个asynchronous的,所以它实际上是一样的表面上奇怪的方式,你的同时计数器。 由于CustomEventEmitter的性质,线程依次执行语句。 你会在浏览器中看到这个jQuery点击事件。 它是同步的,所以所有的事件处理程序语句都在事件循环之前。
所以知道某些东西是否执行asynchronous将有助于理解js代码stream。 while循环和CustomEventEmitter都是同步操作,而fs是asynchronous操作。
希望澄清。