javascript - Node.js writable.write 返回 false?

标签 javascript node.js streamwriter writable

我要上传(流)控制写入过程。但是写入过程总是返回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/

相关文章:

javascript - 尝试为我的 Electron 应用程序创建安装程序时生成未找到错误

javascript - 将 Google Geochart 标记更改为自定义 png 图标

javascript - 如何在 package.json 内的 npm 脚本中使用 SECRET_ENV?

mysql - 用于本地数据库的 AngularJS API,从哪里开始?

c# - StringBuilder.ToString() 抛出 OutOfMemoryException

javascript - Highcharts 双 y 轴标签

javascript - 尝试将 if 嵌入到其他 if 中

node.js - 我如何在 Express 中解析这个 HTTP POST 请求?

c# - 如何使用 XmlWriter 编写格式不正确的 xml

c# - 在C#中写一个带有特殊字符的字符串