简体   繁体   English

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

[英]How to properly react to an error event in a Node.js stream pipe-line?

I was struggling with understanding how error handling works inside a Node.js stream pipeline and I ended up experimenting using a simple playground which made things crystal clear for me. 我一直在努力理解错误处理如何在Node.js流管道中工作,最终我使用了一个简单的游乐场进行试验,这对我来说很清楚。

I am posting this as a self-answered question. 我将其发布为一个自我解答的问题。 Perhaps someone finds it helpful :) 也许有人觉得这很有帮助:)

The playground 操场

Let's create three named PassThrough streams connected into a pipeline and observe individual events. 让我们创建连接到管道中的三个名为PassThrough的流,并观察各个事件。

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);

Standard behaviour 标准行为

Writing to the pipeline is straightforward. 写入管道非常简单。 We simply get a data event from each strem. 我们只是从每个strem中获取一个data事件。

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

Let's see what happens when we end the stream? 让我们看看结束流时会发生什么? No surprises there either. 那里也没有惊喜。

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

Error handling 错误处理

Let's try emitting an error (obviously, if you called the s1.end() above, you need to recreate the pipeline first). 让我们尝试发出一个错误(显然,如果您调用了上面的s1.end() ,则需要先重新创建管道)。

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

Notice nothing else happens here. 注意这里什么也没有发生。 You can continue writing to S1 as if nothing happened. 您可以继续写S1,就像什么都没发生一样。 The pipeline is not closed. 管道未关闭。

Things get a little more interesting when there's an error "mid-stream" :) 当出现“中游”错误时,事情会变得更加有趣:)

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

Notice that Node.js automatically unpipes the S1 stream from S2 but nothing else. 请注意,Node.js会自动从S2取消对S1流的管道传输,除此之外没有其他操作。 Ie the S1 stream still waits for someone to read its data and the S2 stream is still piped into the S3 and can (theoretically) send data. 也就是说,S1流仍在等待某人读取其数据,而S2流仍通过管道传递到S3中,并且可以(理论上)发送数据。

This is something you need to handle in your code! 这是您需要在代码中处理的事情! One option is to call the end() methods on S1 and S2. 一种选择是在S1和S2上调用end()方法。 Another would be to reconnect S1 and S2 with the pipe() method. 另一个方法是使用pipe()方法重新连接S1和S2。 Both seem to work, but it all depends on your particular usage scenario. 两者似乎都可以工作,但这都取决于您的特定使用情况。

Credits 积分

  1. This article from Ben Nadel's blog pointed me in the right direction. Ben Nadel博客的这篇文章为我指明了正确的方向。
  2. This SO question addresses a similar subject from a slightly different perspective. 这个SO问题从稍微不同的角度解决了一个相似的主题。 There are some good pointers in the answers as well. 答案中也有一些很好的指示。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM