当前位置: 首页 > 知识库问答 >
问题:

如何正确应对Node.js管道中的错误事件?

萧远
2023-03-14

我在努力理解错误处理是如何在Node.js流管道内工作的,最后我用一个简单的游乐场进行了实验,这让事情变得非常清楚。

我将此作为一个自我回答的问题发布。也许有人觉得这很有帮助:)

共有1个答案

裴曜灿
2023-03-14

让我们创建三个连接到管道中的命名直通流,并观察各个事件。

var stream = require('stream');

function observedStream(name) {
  var s = new stream.PassThrough({objectMode: true});

  s.on('error', function(err) { console.log(name + ': ' + err); });
  s.on('data', function(data) { console.log(name + ': ' + data); });
  s.on('finish', function() { console.log(name + ': FINISH'); });
  s.on('end', function() { console.log(name + ': END'); });
  s.on('close', function() { console.log(name + ': CLOSE'); });
  s.on('unpipe', function() { console.log(name + ': UNPIPE'); });

  return s;
}

var s1 = observedStream('S1'),
    s2 = observedStream('S2'),
    s3 = observedStream('S3');

s1.pipe(s2).pipe(s3);

写入管道是很简单的。我们只需从每个strem获取一个数据事件。

s1.write('Hello');
// S1: Hello
// S2: Hello
// S3: Hello

让我们看看当我们结束流时会发生什么?那里也没有惊喜。

s1.end();
// S1: FINISH
// S1: END
// S2: FINISH
// S2: UNPIPE
// S2: END
// S3: FINISH
// S3: UNPIPE
// S3: END

让我们尝试发出一个错误(显然,如果调用上面的s1.end(),则需要首先重新创建管道)。

s1.emit('error', new Error('bazinga'));
// S1: Error: bazinga

注意这里没有发生其他事情。你可以继续给S1写信,就像什么都没发生一样。管道没有关闭。

事情变得更有趣,当有一个错误"中流":)

s2.emit('error', new Error('bazinga'));
// S2: UNPIPE
// S2: ERROR

请注意该节点。js自动将S1流从S2中取消管道连接,但不执行其他操作。即,S1流仍然等待有人读取其数据,S2流仍然通过管道传输到S3,并且可以(理论上)发送数据。

这是您需要在代码中处理的事情!一个选项是在S1和S2上调用end()方法。另一种方法是使用pipe()方法重新连接S1和S2。这两种方法似乎都有效,但这取决于您的特定使用场景。

  1. 本·纳德尔博客上的这篇文章给我指明了正确的方向。
  2. 这个SO问题从一个稍微不同的角度解决了一个类似的问题。答案中也有一些好的建议。
 类似资料:
  • 问题内容: 我有很多数据要插入(SET \ INCR)到redis DB,所以我正在寻找通过 node.js* 进行管道 \ 大量插入的操作。 * 我在node.js中找不到任何好的示例/ API,因此任何帮助都将非常有用! 问题答案: 是的,我必须同意缺少示例,但是我设法创建了一个流,在该流上我批量发送了几个插入命令。 您应该为redis流安装模块: 这就是您使用流的方式: 另外,您可以根据需要

  • 现在,越来越多的科技公司和开发者开始使用 Node.js 开发各种应用。Node.js除了能够辅助大前端开发外,还可以编写Web应用,封装Api,组装RPC服务等,甚至是开发 VSCode 编辑器一样的PC客户端。和其它技术相比, Node.js 简单易学,性能好、部署容易,能够轻松处理高并发场景下的大量服务器请求。Node.js 周边的生态也非常强大,NPM(Node包管理)上有超过60万个模块

  • 问题内容: 我有这个错误: 当但奇怪的是,更新此插件时发生错误:管道共享Groovy库,在此工作正常之前,我使用jenkins v 2.21和管道2.4,而我的代码是下一个: 问题答案: Jenkins作业可以保存在执行中,这需要对它们进行序列化。rawBuild的内容无法序列化,因此,如果要访问它,则需要在以开头的函数中进行序列化。例如:

  • 问题内容: 我一直在尝试在Node.js中调用D3。我首先尝试使用脚本标签从D3的网站导入d3.v2.js D3的作者建议一个人应该“ npm install d3” …我做到了,我可以在节点控制台中成功调用它: 但是,当尝试使用“ node app.js”从app.js调用它时,我得到: 我意识到,D3的作者在其他地方已经明确规定了应该使用画布: https://github.com/mbost

  • 问题内容: 如何在node.js中创建命名管道? PS:目前,我正在按如下方式创建命名管道。但是我认为这不是最好的方法 问题答案: 看起来,Node核心不支持名称管道-从Ben Noordhuis 11/10/11开始: Windows具有命名管道的概念,但是自您提到以来,我假设您的意思是UNIX FIFO。 我们不支持它们,可能永远也不会(在非阻塞模式下的FIFO可能会死锁事件循环),但是如果您

  • 问题内容: 当我的discord bot上网时间过长(大约3-4小时)时,会随机出现此错误,但有时该错误发生得更早,有时又更晚。真的很困扰我 问题答案: 我在自己的代码中为这个问题努力了一段时间。主要问题是跟踪是完全无用的, 并且 错误很少发生,以至于使“在终端中运行并等待”是徒劳的任务。最终,我能够弄清楚Discord.js客户端本身正在引发错误- 在我阅读的任何文档中都没有提到此错误,因此我没