The biggest problem with forwarding errors happens when you have
duplex streams that forward to one another, and as Martin points out,
streams that emit errors in different circumstances.
For example, let's say that you added something like this in the
pipe() function:
src.on('error', function(er) {
dest.emit('error', er);
});
What happens when you do this?
// encryptor service
net.createServer(function (socket) {
socket.pipe(new Encryptor()).pipe(socket);
});
If the socket emits error, it forwards to the encryptor, which
forwards it to the socket, and it's an infinite loop. Now every
encryption error is also a RangeError!
You *could* make this work by keeping track of whether a stream's
error events are already forwarded, but that's just more state
tracking and complexity, and it ends up being somewhat
indeterministic. For example, these two servers would be
error-forwarded differently, though they should be semantically
equivalent:
net.createServer(function (socket) {
// all errors emit on socket
var e = new Encryptor();
e.pipe(socket).pipe(e);
});
net.createServer(function (socket) {
// all errors emit on encryptor
var e = new Encryptor();
socket.pipe(e).pipe(socket);
});
To Martin's point, this also obscures the source of the error. Though
it's more verbose, stuff like this is actually quite important:
fs.createReadStream(tarball)
.on('error', handleFileReadError)
.pipe(gzip.Gunzip())
.on('error', handleUnzipError)
.pipe(tar.Extract({ path: targetPath }))
.on('error', handleTarExtractError)
.on('close', cb)
All those different errors have different information, metadata, etc.,
and in many cases, if you don't know the object that emitted them,
then you don't have a lot of insight into what error message you
should print out. ("Your program says 'illegal data', what's going
wrong?" Good luck debugging that!)
The moral of the story is that you must either attach error listeners
to all streams you touch, or accept that they will throw (and perhaps
gather all throws into a domain). For example, if you really *wanted*
to only have a single error handler you could do this:
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 is actually not so bad. Domains add a bit of metadata to the
error object, so it's not too hard to figure out whether it was an
"organic" throw, or an error event that was emitted by some object.
On Wed, Nov 28, 2012 at 9:54 PM, Martin Cooper <[email protected]> wrote:
>
>
> On Wed, Nov 28, 2012 at 2:05 PM, Jeff Barczewski <[email protected]>
> wrote:
>>
>> Agreed. Especially if the error happens after the initial connection
>> (which is probably when most would occur), then it won't be caught by any
>> try/catch so it would have to rely on domains.
>>
>> If you have setup an error handler then it is just nice to deal with it
>> there in one spot.
>
>
> That depends on what you're going to do with it. As a simple example, if I
> create a read stream on a tarball, pipe it through Gunzip, and pipe that
> through Untar, I may well be interested in reporting to the user which one
> of those things messed up if something went wrong. What I *don't* want to
> have to do is muddle through inconsistently constructed Error objects to try
> to figure that out for myself, if there's only one place to put my error
> handler.
>
> In other words, I *like* the fact that the error handlers are interspersed
> within my pipe setup, because it gives me flexibility in both determining,
> and reporting, what went wrong. If I don't want to make use of that
> flexibility, then I can reuse the same handler, as in your example. But I
> have that choice.
>
> --
> Martin Cooper
>
>> --
>> Job Board: http://jobs.nodejs.org/
>> Posting guidelines:
>> https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
>> You received this message because you are subscribed to the Google
>> Groups "nodejs" group.
>> To post to this group, send email to [email protected]
>> To unsubscribe from this group, send email to
>> [email protected]
>> For more options, visit this group at
>> http://groups.google.com/group/nodejs?hl=en?hl=en
>
>
> --
> Job Board: http://jobs.nodejs.org/
> Posting guidelines:
> https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
> You received this message because you are subscribed to the Google
> Groups "nodejs" group.
> To post to this group, send email to [email protected]
> To unsubscribe from this group, send email to
> [email protected]
> For more options, visit this group at
> http://groups.google.com/group/nodejs?hl=en?hl=en
--
Job Board: http://jobs.nodejs.org/
Posting guidelines:
https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en