如何正确地对Node.jsstreampipe道中的错误事件做出反应?

我在理解error handling是如何在一个Node.jsstreampipe道中工作的,并且我最终使用一个简单的操作系统进行了实验。

我发布这个自我回答的问题。 也许有人认为它有帮助:)

操场

让我们创build三个连接到pipe道中的已命名的PassThroughstream,并观察单个事件。

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

标准行为

写入pipe道很简单。 我们只是从每个strem获得一个data事件。

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

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

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

error handling

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

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

注意这里没有其他事情发生 如果没有任何事情发生,你可以继续写S1。 pipe道没有closures。

当“中stream”出现错误时,事情会变得更有趣

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

请注意,Node.js自动从S2处理S1stream,但没有别的。 即S1stream仍然等待有人读取其数据,并且S2stream仍然被传送到S3,并且可以(理论上)发送数据。

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

积分

  1. Ben Nadel博客的这篇文章指出了我的正确方向。
  2. 这个SO问题从一个稍微不同的angular度来处理类似的问题。 答案中也有一些好的指针。