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操作。

希望澄清。