首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >node.js streams的错误处理

node.js streams的错误处理
EN

Stack Overflow用户
提问于 2014-02-14 13:02:23
回答 9查看 96.3K关注 0票数 181

处理streams错误的正确方法是什么?我已经知道有一个'error‘事件你可以收听,但我想知道更多关于任意复杂情况的细节。

对于初学者来说,当你想做一个简单的管道链时,你该怎么做:

input.pipe(transformA).pipe(transformB).pipe(transformC)...

如何正确地创建这些转换之一,以便正确处理错误?

更多相关问题:

  • 当发生错误时,'end‘事件会发生什么?它从来不会被解雇吗?它有时会被解雇吗?它依赖于转换/流吗?这里的标准是什么?
  • 是否有通过管道传播错误的机制?
  • 域是否有效地解决了这个问题?
  • 从'error‘事件中产生的错误会有堆栈跟踪吗?有时候?绝不可能?有没有办法从他们那里得到一个?
EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2014-03-14 03:55:01

变换

转换流既是可读的也是可写的,因此是真正好的“中间”流。因此,它们有时被称为through流。它们在这种方式上类似于双工流,只是它们提供了一个很好的接口来操作数据,而不仅仅是发送数据。转换流的目的是在通过流传输数据时对其进行操作。例如,你可能想做一些异步调用,或者派生几个字段,重新映射一些东西,等等。

有关如何创建转换流的信息,请参见herehere。你要做的就是:

转换方法包括流module

  • instantiate (或继承自)
  1. 实现一个接受(chunk, encoding, callback)_transform方法。

数据块就是你的数据。大多数情况下,如果您使用的是objectMode = true,就不需要担心编码问题。当您完成对块的处理时,将调用该回调。然后将此块推送到下一个流。

如果你想要一个很好的帮助器模块,让你可以非常非常容易地通过stream进行操作,我建议使用through2

对于错误处理,请继续阅读。

管道

在管道链中,处理错误确实不是微不足道的。根据this thread的说法,.pipe()不是用来转发错误的。所以像这样的东西。

代码语言:javascript
复制
var a = createStream();
a.pipe(b).pipe(c).on('error', function(e){handleError(e)});

..。将仅侦听流c上的错误。如果在a上发出错误事件,则不会向下传递,实际上会抛出。要正确执行此操作,请执行以下操作:

代码语言:javascript
复制
var a = createStream();
a.on('error', function(e){handleError(e)})
.pipe(b)
.on('error', function(e){handleError(e)})
.pipe(c)
.on('error', function(e){handleError(e)});

现在,虽然第二种方法更加冗长,但您至少可以保留错误发生位置的上下文。这通常是一件好事。

但是,如果您有这样一种情况,即只想捕获目的地的错误,而不太关心它发生在哪里,那么我发现有一个库很有用,那就是event-stream

结束

当错误事件被激发时,end事件将不会被(显式地)激发。错误事件的发出将结束流。

根据我的经验,域在大多数情况下都运行得很好。如果有未处理的错误事件(即在没有侦听器的情况下在流上发出错误),服务器可能会崩溃。现在,正如上面的文章所指出的,您可以将流包装在一个能够正确捕获所有错误的域中。

代码语言:javascript
复制
var d = domain.create();
 d.on('error', handleAllErrors);
 d.run(function() {
     fs.createReadStream(tarball)
       .pipe(gzip.Gunzip())
       .pipe(tar.Extract({ path: targetPath }))
       .on('close', cb);
 });

上面的代码示例来自this post

域的美妙之处在于它们将保留堆栈跟踪。尽管event-stream在这方面也做得很好。

要进一步阅读,请查看stream-handbook。非常深入,但非常有用,并提供了许多有用模块的链接。

票数 244
EN

Stack Overflow用户

发布于 2018-11-12 19:33:42

如果您使用的是node >= v10.0.0,则可以使用stream.pipelinestream.finished

例如:

代码语言:javascript
复制
const { pipeline, finished } = require('stream');

pipeline(
  input, 
  transformA, 
  transformB, 
  transformC, 
  (err) => {
    if (err) {
      console.error('Pipeline failed', err);
    } else {
      console.log('Pipeline succeeded');
    }
});


finished(input, (err) => {
  if (err) {
    console.error('Stream failed', err);
  } else {
    console.log('Stream is done reading');
  }
});

有关更多讨论,请参阅此github PR

票数 37
EN

Stack Overflow用户

发布于 2015-12-29 18:14:47

域已弃用。你不需要他们。

对于这个问题,transform和writable之间的区别并不那么重要。

mshell_lauren的答案很好,但作为替代方案,您还可以显式侦听您认为可能出错的每个流上的error事件。如果您愿意,还可以重用处理程序函数。

代码语言:javascript
复制
var a = createReadableStream()
var b = anotherTypeOfStream()
var c = createWriteStream()

a.on('error', handler)
b.on('error', handler)
c.on('error', handler)

a.pipe(b).pipe(c)

function handler (err) { console.log(err) }

这样做可以防止在其中一个流触发其错误事件时出现臭名昭著的未捕获异常

票数 26
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21771220

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档