是否可以编写非阻塞response.write?我写了一个简单的测试,看看其他客户端是否可以在下载文件时连接:
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
正在阻止!
我做错了吗?
更新因此,它不会阻止并且它会在同一时间阻止。在两个文件可以同时下载的意义上它不会阻塞。并且它在某种意义上阻止了创建缓冲区是一个很长的操作。
答案 0 :(得分:2)
任何严格按JavaScript完成的处理都会阻止。 response.write()
,至少从v0.8开始,no exception为stream:
第一次调用
response.write()
时,它会将缓冲的头信息和第一个主体发送到客户端。第二次调用response.write()
时,Node假定您将要传输数据,并单独发送。也就是说,响应被缓冲到第一个身体块。如果将整个数据成功刷新到内核缓冲区,则返回
true
。如果全部或部分数据在用户内存中排队,则返回false
。当缓冲区再次释放时,将发出'drain'
。
可以节省一些时间是在尝试longString
之前将Buffer
转换为write()
,因为无论如何转换都会发生:
var longString = 'a';
for (...) { ... }
longString = new Buffer(longString);
但是,对longString
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();
}
的各个块而不是一次性({注释:Streams are changing in v0.10)可能会更好{<3}}:
function download(request, response) {
// response.setHeader(...)
// ...
fs.createReadStream('./file-on-disk').pipe(response);
}
而且,如果最终目标是从磁盘流式传输文件,fs.createReadStream()
和stream.pipe()
可以更轻松地实现这一目标:
{{1}}
答案 1 :(得分:1)
不,它没有阻止,我尝试了一个来自IE和其他来自Firefox。我先做IE,但仍然可以先从firefox下载文件。 我尝试了1 MB(i&lt; 20)它的工作速度相同。 你应该知道你创建的longString需要内存分配。尝试为我做&< 30(在Windows 7上)它将抛出致命错误:JS分配失败 - 处理内存不足。
内存分配/复制需要时间。由于它是一个巨大的文件,响应是耗时的,你的下载看起来像阻止。自己尝试使用较小的值(i <20或其他)