As I understand it async/await is largely syntactic sugar on top of promises. Specifically I think that since ReadableStream.pipe follows an event-based (on("error", errorHandler)
) rather than promise-based pattern, the try { ... await ... } catch (ex) { ... }
construction isn't going to handle asynchronous errors "thrown" within ReadableStream.pipe as seamlessly as you might hope.
Assuming my understanding is correct (and to be honest I don't use the aysnc/await syntax often, so it's possible I'm missing something too) one straightforward work-around is to fall back to adding a callback-based event handler like this:
function handleError(err) { ... }
readable.once("error", handleError);
// and if you want, re-use that handler within your catch block, like:
// `} catch (ex) { handleError(ex); }`
// but I'm not sure how often that will come up if you follow this pattern
but you may already be aware of that.
Failing that, if you really want to use the aysnc/await/try/catch-style construction in this case you could use something like util.promisify
to convert the on("error", handler)
-event-based API that ReadableStream is using to promises. This StackOverflow post - How to use Async await using util promisify? - covers that topic in more depth but (IMO) that seems like a lot of hoops to jump through just to avoid adding readable.once("error" /* ...whatever you'd otherwise have in your catch block ... */)
In short, I think because ReadableStream.pipe isn't designed around promises, the async/await syntax isn't enough (in and of itself) to ensure that the asynchronous errors that might be emitted as on-error events are trapped by the try/catch block. You need to handle those errors in the old-school way, either directly (by registering a handler for the error events emitted by your readable
, in which case the await and try/catch stuff isn't directly applicable) or "indirectly" (by creating an adapter that makes those emitted-events bubble up like the catch case on a resolved promise, in which case you can make it look like a synchronous-style try/catch using async/await).