node.js - 按时附加事件处理程序

San*_*an4 7 javascript-events node.js

我正在研究node.js并在node.js手册中遇到了这个例子:

...
var req = http.request(options);
req.end();

req.on('upgrade', function(res, socket, upgradeHead) {
  console.log('got upgraded!');
  socket.end();
  process.exit(0);
});
...
Run Code Online (Sandbox Code Playgroud)

我在这个例子中看到的是,创建请求之后,甚至在(计划发送)之后,处理程序附加到HTTP请求事件.更糟糕的是,手册说:

如果未侦听此事件,则接收升级标头的客户端将关闭其连接.

事件是否有可能 req.on(...有机会附加处理程序之前发生?我怀疑我对节点异步模型中的某些内容并不了解.或者这个代码来自节点手册,希望网络请求比执行下一行代码需要更长的时间?

另一个例子:

http.get("http://www.google.com/index.html", function(res) {
  console.log("Got response: " + res.statusCode);
}).on('error', function(e) {
  console.log("Got error: " + e.message);
});
Run Code Online (Sandbox Code Playgroud)

这里,HTTP请求将在创建对象后立即启动,之后我们才会附加错误处理程序.同样,(1)它是一个仅因网络延迟而起作用的代码,(2)我没有得到关于node.js概念的东西,或者(2b)事件将"等待"直到我附加一个处理程序?

编辑:更好的例子,也来自手动.下面的好的坏的例子是不同的,因为在好的例子中我们足够快地附加事件,因此错过数据的机会很少,或者永远不可能以这种方式错过数据(为什么?!)

// Good
request.on('response', function (response) {
  response.on('data', function (chunk) {
    console.log('BODY: ' + chunk);
  });
});

// Bad - misses all or part of the body
request.on('response', function (response) {
  setTimeout(function () {
    response.on('data', function (chunk) {
      console.log('BODY: ' + chunk);
    });
  }, 10);
});
Run Code Online (Sandbox Code Playgroud)

fre*_*ish 6

你想念的是JavaScript根本不是异步的!我的意思是JavaScript是单线程的,异步操作实际上并不是异步的.有一个非常奇特的队列模型,它给出了JavaScript异步的错觉(不要误解我:它仍然最有效的模型).

那是什么意思呢?这意味着一旦同步代码运行,其他代码就不可能并行运行.例如,在此代码中

var req = http.request(options);
req.end();
req.on(...);
Run Code Online (Sandbox Code Playgroud)

请求已安排,但主线程(即操作)尚未结束req.end().只要主操作没有完成,就不会发生异步代码.特别是在实际事件有可能发生之前总是设置处理程序.

再举一个让它更清晰的例子.考虑以下代码:

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
    while(true) { } // <------ infinite loop doing nothing
}).listen(1337, '127.0.0.1');
Run Code Online (Sandbox Code Playgroud)

请注意,第一个请求将成功完成.但任何其他请求永远不会得到回应.这是因为循环永远不会完成操作,因此JavaScript 无法跳转到另一个事件.这段代码永远崩溃了应用程序,超出了任何希望.所以要小心使用Node.js的同步代码.:)