是http.ServerResponse.write()阻塞?

有没有可能写非阻塞response.write? 我已经写了一个简单的testing,看看其他客户端可以连接,而一个下载文件:

var connect = require('connect'); var longString = 'a'; for (var i = 0; i < 29; i++) { // 512 MiB longString += longString; } console.log(longString.length) function download(request, response) { response.setHeader("Content-Length", longString.length); response.setHeader("Content-Type", "application/force-download"); response.setHeader("Content-Disposition", 'attachment; filename="file"'); response.write(longString); response.end(); } var app = connect().use(download); connect.createServer(app).listen(80); 

这似乎是write封锁!

难道我做错了什么?

更新所以,它不会阻塞,并在同一时间阻止。 这并不意味着可以同时下载两个文件。 而且它阻止了创build缓冲区是一个漫长的操作。

任何严格的JavaScript处理都将被阻止。 response.write() ,至less从v0.8开始, 也不例外 :

第一次调用response.write() ,它会将caching的头信息和第一个正文发送给客户端。 第二次调用response.write() ,Node假定你要传输数据,并分别发送。 也就是说,响应被缓冲到第一个主体。

如果整个数据已成功刷新到内核缓冲区,则返回true 。 如果全部或部分数据在用户存储器中排队,则返回false 。 当缓冲区再次空闲时,将会发出'drain'

什么可以节省一些时间是在尝试write()之前将longString转换为Buffer ,因为无论如何都会发生转换:

 var longString = 'a'; for (...) { ... } longString = new Buffer(longString); 

但是,可能会更好地将longString的各个部分进行stream式处理,而不是一次全部处理(注意: stream在v0.10中正在改变 ):

 var longString = 'a', chunkCount = Math.pow(2, 29), bufferSize = Buffer.byteLength(longString), longBuffer = new Buffer(longString); function download(request, response) { var current = 0; response.setHeader("Content-Length", bufferSize * chunkCount); response.setHeader("Content-Type", "application/force-download"); response.setHeader("Content-Disposition", 'attachment; filename="file"'); function writeChunk() { if (current < chunkCount) { current++; if (response.write(longBuffer)) { process.nextTick(writeChunk); } else { response.once('drain', writeChunk); } } else { response.end(); } } writeChunk(); } 

而且,如果最终目标是从磁盘stream式传输文件,使用fs.createReadStream()stream.pipe()可以更容易:

 function download(request, response) { // response.setHeader(...) // ... fs.createReadStream('./file-on-disk').pipe(response); } 

不,它不阻止,我尝试了一个从IE和Firefox等。 我做了第一个IE,但仍然可以从Firefox下载文件。 我尝试了1 MB(我<20),它只是更快地工作。 你应该知道,无论你创build什么longString都需要内存分配。 尝试做我为<30(在Windows 7),它会抛出致命错误:JS分配失败 – 进程内存不足。

内存分配/复制需要时间。 由于它是一个巨大的文件,反应是时间和你的下载看起来像阻塞。 自己尝试一下较小的值(我<20或某物)