0

I have the following situation.

function emitErrorInStream() {
  let resultStream = new PassThrough();
  let testStream = new PassThrough();
  testStream.on("error", () => {
    throw new Error("AA");
  } 
  // the setTimeout simulates what is actually happening in the code.

  /*
  * actual code
  * let testStream = s3.getObject(params).createReadStream();
  * if I pass in an incorrect parameter option to the getObject function
  * it will be a few milliseconds before an error is thrown and subsequently caught by the stream's error handling method.
  */
  setTimeout(() => {testStream.emit("error", "arg");}, 100);
  return testStream.pipe(resultStream);
}

try{
  let b = emitErrorInStream();
}
catch(err){
  console.log(err) // error will not be caught
}


///... continue

I have tried a slew of things to catch the error thrown inside the error handler. I have tried using promises, which never resolve. How can I catch the error thrown inside thetestStream's error handler?

I have found that sending an end event inside the on("error") handler partially solves my issue as it does not crash the application running. It is not a recommended solution https://nodejs.org/api/stream.html#stream_event_end_1

Lastly, is catching this error possible if emitErrorInStream is a third party function to which I do not have access?

Any insights would be greatly appreciated.

// actual typescript code
downloadStream(bucketName: string, filename: string): Stream {
  const emptyStream = new PassThrough();
  const params = { Bucket: bucketName, Key: filename };
  const s3Stream = this.s3.getObject(params).createReadStream();

  // listen to errors returned by the service. i.e. the specified key does not exist.
  s3Stream.on("error", (err: any) => {
    log.error(`Service Error Downloading File: ${err}`);
    // Have to emit an end event here.
    // Cannot throw an error as it is outside of the event loop
    // and can crash the server.
    // TODO: find better solution as it is not recommended https://nodejs.org/api/stream.html#stream_event_end_1
    s3Stream.emit("end");
  });
  return s3Stream.pipe(emptyStream);
}
M.Nar
  • 512
  • 1
  • 9
  • 24
  • https://stackoverflow.com/questions/48969591/why-promise-can-not-catch-the-error-throw-by-settimeout – chiliNUT Nov 05 '20 at 04:47
  • I understand this. Which is why I am asking the question in the first place. I put an example of what is happening using `setTimeout`. The setTimeout is a replacement for an action that happens outside of my control. – M.Nar Nov 05 '20 at 04:58
  • You don't throw inside asynchronous event handlers. It never works properly and there is no work-around wither. You can wrap the entire thing in a promise, return the promise from your function and reject that promise when an error occurs on the stream. That will communicate back the failure. Similarly, you would resolve the promise when the stream completes its job successfully. Otherwise, the caller needs to monitor the stream itself for `error` events. – jfriend00 Nov 05 '20 at 04:58
  • I tried wrapping my code in a promise. It would never resolve. Unless I made a mistake in how I wrote it. Can you show me how you would wrap the code in a promise that resolved and rejected appropriately? – M.Nar Nov 05 '20 at 05:06
  • @M.Nar - You would have to show more of the real code and describe how you know the operation is done because that's where you would resolve the promise. – jfriend00 Nov 05 '20 at 05:07
  • yes like @jfriend00 said you can't resolve asynchronous in synchronous try catch method, wrap in promise or use callback – syarul Nov 05 '20 at 05:56

0 Answers0