我想上传(流)控制写入过程。但是写入过程总是返回false。大文件上载过程停止。代码的输出如下;
> Node app.js
> False
> False
> False
> False我做错了什么?
我的代码;
app.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);发布于 2016-10-24 22:36:15
我已经修改了你的程序,以显示有关正在发生的事情的更多信息:
'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()返回的每个块都足够大,从而导致写操作流超出其highWaterMark,后者默认为16384 (假设fs.createWriteStream返回的流)。从输出中的数字可以看出,除了最后一个之外,每个read() (err,每个'data'事件)都会产生65536字节。由于将此数量的数据写入writable会导致其超出其highWaterMark,因此该流建议在继续之前等待'drain'。
因此,简单地说,您总是会看到false被发出,因为readable流在读取时会产生如此大的块。我希望再也看不到任何日志,这表明传输已完成。但是你真的需要注册.on('end')和.on('error')才能解决这个问题。
对于这样一个简单的例子,最好只使用readable.pipe(),比如:
readable.pipe(writable);这将自动为您处理'drain'。它甚至会适当地为你调用writable.end()。
请注意,如果遇到读取或写入错误,pipe()将不会调用writable.end()。如果您有一个长时间运行的进程,需要对流错误具有弹性,则需要确保处理错误并关闭流,以防止在程序运行足够长的时间达到文件描述符限制时出现句柄泄漏。
false是什么意思
流使程序能够通过一次处理一个块而不是将其全部加载到内存中来扩展到大量数据。在数据最终被写出之前,流可以被组织成表示数据上的各种变换的管道。当write()返回false时,它发出信号表示它已经收到了足够的数据,足以让它忙碌一段时间。如果你继续向它发送数据块,它将继续接受这些数据块。然而,它的数据积压将会增长,并开始消耗更多的内存。如果您忽略此返回值,并不断向其发送来自非常大的源的数据,您甚至可能导致程序耗尽其地址空间并崩溃或被卡住。为了保持代码的可伸缩性,您应该像在代码中一样,尊重false返回并等待'drain。
但是,false并不意味着发生了任何不好的事情,也不意味着有任何错误。事实上,在源流比目标流更快的任何场景中,这都是可以预料到的,也是streams API保证安全的方式。
https://stackoverflow.com/questions/33026112
复制相似问题