首先,让我们弄清楚
EventEmitter
是。因此node.js是
asynchronous
. 这意味着,不必等待服务器对象上的传入连接,而是添加
listener
传递给对象
callback function
然后,“一旦”事件发生,就会被执行。
在后台仍有很多人在等待,但这些都是从你那里抽象出来的。
让我们来看一个简单的例子:
// #1) create a new server object, and pass it a function as the callback
var server = net.createServer(function (stream) {
// #2) register a callback for the 'connect' event
stream.on('connect', function () {
stream.write('hello\r\n'); // as
});
// #3) register a callback for the 'data' event
stream.on('data', function (data) {
stream.write(data);
});
// #4) register a callback for the 'end' event
stream.on('end', function () {
stream.write('goodbye\r\n');
stream.end();
});
});
// #5) make the server listen on localhost:8124
server.listen(8124, 'localhost');
所以我们创建服务器并将其传递给
回调函数
,此函数尚未执行。在这里传递函数基本上是为
connection
服务器对象的事件。之后,我们启动服务器
#5
.
现在,如果是传入连接,会发生什么情况?
-
因为我们传递给
createServer
被束缚在
连接
事件,它现在被执行。
-
它增加了
connect
,
data
和
end
事件侦听器
stream object
(表示单个连接)通过连接事件的回调。
-
之后,
stream
开火
连接
事件,因此函数在
#2
执行并写入
hello\r\n
流向溪流。函数如何知道应该写入哪个流?
Closures
答案是,函数继承了它在其中创建的作用域,因此在函数内部
流动
仍在引用触发这个回调的单个连接。
-
现在,客户机通过连接发送一些数据,这使得
流动
对象调用它的
数据
事件,因为我们在
#3
现在,我们将传入的数据回送到客户机。
-
如果客户机关闭了连接,我们所绑定的函数
#4
被调用,写入
goodbye\r\n
在那之后,我们这边的连接就关闭了。
这能让事情更清楚一点吗?好吧,这确实让整个事情变得容易多了。就像javascript在浏览器中一样,
single threaded
. 在某一时刻只有一件事发生。
简单地说,所有这些
callbacks
以一个全局队列结束,然后一个接一个地被调用,因此这个队列(抽象的)可能如下所示:
| connection event for a new stream
| data event for stream #12
| callback set via setTimeout
v close event of yet another stream
现在这些都是自上而下执行的,它们之间不会发生任何事情。没有机会,当你在
callback
绑定到
数据
事件,会有其他事情发生,并神奇地改变系统的状态。即使服务器上有一个新的传入连接,它的事件也将被排队,并且必须等到所有事情发生之前,包括
数据
您当前所在的活动,结束。