Javascript 如何正确响应Node.js流管线中的错误事件?

Javascript 如何正确响应Node.js流管线中的错误事件?,javascript,node.js,stream,Javascript,Node.js,Stream,我一直在努力理解Node.js流管道中的错误处理是如何工作的,最后我用一个简单的游乐场进行了实验,这让我非常清楚 我将此作为一个自我回答的问题发布。也许有人觉得它很有用:)操场 让我们创建三个连接到管道中的命名直通流,并观察各个事件 var stream = require('stream'); function observedStream(name) { var s = new stream.PassThrough({objectMode: true}); s.on('error

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

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

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

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,就好像什么都没发生一样。管道没有关闭

当出现错误“中流”时,事情会变得更有趣一些:

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

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

信用
  • Ben Nadel的博客为我指明了正确的方向
  • 从稍微不同的角度处理类似的主题。答案中也有一些很好的提示
  • s1.emit('error', new Error('bazinga'));
    // S1: Error: bazinga
    
    s2.emit('error', new Error('bazinga'));
    // S2: UNPIPE
    // S2: ERROR