我要上传(流)控制写入过程。但是写入过程总是返回false。大文件上传过程停止。代码输出结果如下;
> Node app.js
> False
> False
> False
> False
我做错了什么?
我的代码;
应用程序.js
var http = require('http');
var fs = require('fs');
http.createServer(function(req, res){
var readable = fs.createReadStream('read.mkv');
var writable = fs.createWriteStream('write.mkv');
readable.on('data', function(chunk){
var buffer = writable.write(chunk);
if(!buffer){ // ----> Always false! Why????
readable.pause();
}
console.log(buffer);
});
writable.on('drain', function(){
readable.resume();
});
}).listen(8090);
最佳答案
我已修改您的程序以显示有关正在发生的事情的更多信息:
'use strict';
const fs = require('fs');
const readable = fs.createReadStream('read.mkv');
const writable = fs.createWriteStream('write.mkv');
readable.on('data', function(chunk){
var buffer = writable.write(chunk);
if(!buffer){ // ----> Always false! Why????
readable.pause();
}
console.log(buffer, chunk.length);
});
writable.on('drain', function(){
readable.resume();
console.log('drain');
});
输出:
$ node blah.js
false 65536
drain
false 65536
drain
false 65536
drain
true 8192
我还使用了一个不同大小的文件作为输入,所以我有一个 true
在我的输出结束时。如果我增加我的 read.mkv
的大小,例如 10000
字节,最后一行将显示为 false 18192
.
发生的事情是 read()
返回的每个 block 足够大,导致写入流超过其 highWaterMark
默认为 16384
(假设 fs.createWriteStream
返回的流)。从输出中的数字可以看出,每个 read()
(错误,每个 'data'
事件)产生 65536
除最后一个字节外的字节。由于将此数据量写入 writable
导致它超过其 highWaterMark
, 该流建议等待 'drain'
在继续之前。
所以,很简单,您总是看到 false
发射是因为 readable
流在读取时会产生如此大的 block 。我希望不再看到任何日志表明传输已完成。但是你真的需要注册 .on('end')
和 .on('error')
弄清楚这一点。
对于像这样的简单情况,使用 readable.pipe()
确实更好。 ,比如:
readable.pipe(writable);
这会自动处理'drain'
为你。它甚至会调用 writable.end()
适合你。
请注意 pipe()
不会调用writable.end()
如果遇到读取或写入错误。如果您有一个长时间运行的进程需要对流错误具有弹性,那么如果您的程序运行时间足以达到文件描述符限制,则需要确保处理错误并关闭流以防止句柄泄漏。
什么false
手段
Streams 使程序能够通过一次处理一个 block 而不是将其全部加载到内存中来扩展到大量数据。在数据最终写出之前,流可以组织成表示数据各种转换的管道。当write()
返回 false
,它表示它已收到足够的数据以使其忙碌一段时间。如果你继续向它发送 block ,它会继续接受这些 block 。但是,它的数据积压将增长并开始消耗更多内存。如果你忽略这个返回值并继续从一个非常大的源发送数据,你甚至可能导致程序耗尽它的地址空间并崩溃或卡住。为了保持代码的可扩展性,您应该尊重 false
返回并等待'drain
' 就像您在代码中所做的那样。
然而,false
并不意味着发生了任何不好的事情或有任何错误。事实上,在源流比目标流快的任何情况下,这种情况都是预期会发生的,这也是流 API 确保事情安全的方式。
关于javascript - Node.js writable.write 返回 false?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33026112/