为什么我们需要res.on('data'…为POST定义,即使我们没有对数据做任何事情?

发现这个问题debugging代码,其中以下不起作用:

var req = http.request(options,function(res){ // res.on('error',cb(err)); res.on('end',function(){ cb(); }); }); 

但是,下面的工作:

  var req = http.request(options,function(res){ // res.on('error',cb(err)); res.on('data',function(chunk){ //why do we need this? }); res.on('end',function(){ cb(); }); }); 

resvariables是一个可读stream 。 如果您点击链接并向下滚动到“结束”事件,您可能会发现以下内容:

请注意,“结束”事件将不会触发,除非数据完全消耗。

通过添加“数据”事件处理程序,您将消耗数据。

在这个实现中, function(res)是一个callback,它必须为至less'data''end'事件注册监听器,即使它们实际上没有做任何事情。

从官方文档 :

在“响应”事件期间,可以将侦听器添加到响应对象; 特别是倾听“数据”事件。

如果没有添加“响应”处理程序,那么响应将被完全丢弃。 但是,如果添加一个“响应”事件处理程序,则必须从响应对象中消费数据,无论何时出现“可读”事件,或通过添加“数据”处理程序,都要调用response.read()通过调用.resume()方法。 在数据消耗之前,“结束”事件不会触发。 此外,直到数据被读取,它会消耗内存,最终可能导致“处理内存不足”的错误。

这就是节点背压机制的工作原理。 如果响应stream的缓冲区填满,它会通知服务器停止发送数据(这是在TCP层处理的)。 所以一旦你开始读取数据(通过res.read()或者附加一个data处理程序或者简单地使用res.resume() ),就会传输更多来自服务器的数据,直到没有更多数据。 只有服务器没有更多的数据发送,你会得到一个end事件。 我通常使用res.resume(); 因为它要短很多

自从节点v0.10以来,这种行为已经存在。 在此之前,如果您没有立即附加data处理程序,则实际上可能会丢失数据,因此您可以想象这会给很多人造成问题。 因此,对于节点v0.10 +,默认行为是暂停直到您开始读取(这是在节点stream层,从networking分开)。