Steven Lu
Steven Lu

Reputation: 43437

Why is it not possible to try/catch some things?

For example I just tried to catch ENOENT by naively doing this:

try {
  res.sendFile(path);
} catch (e) {
  if (e.code === 'ENOENT') {
    res.send('placeholder');
  } else { throw e; }
}

This doesn't work!

I know that the right way is to use the error callback of sendFile, but it's really surprising and bad for me that the fundamental language feature of exceptions doesn't work here.

I guess maybe express itself is doing the catching. And they want to not have the errors kill the server so quickly. It's understandable.

But I just get this lame message:

Error: ENOENT: no such file or directory, stat '<file>' at Error (native)

Not great.

Upvotes: 1

Views: 95

Answers (3)

Craig Tullis
Craig Tullis

Reputation: 10497

Generally speaking, you want to avoid using exceptions to control program flow.

Also, since you're apparently programming this in Node.js, you pass a callback function to keep Node running asynchronously. Node.js is not multithreaded, because JavaScript is not multithreaded, so it cannot have more than one thing going on at a time. That means that if your code is hung up handling an exception, nothing else is happening. And Exceptions are expensive. Doing expensive cleanup in a single-threaded server-side application will harm performance and scalability. Nor is JavaScript itself magically asynchronous. It's asynchronous only if you use callback functions to loosen it up.

So when you pass a callback function to res.send, that function gets called asynchronously when the res.send function finishes (or exits without finishing due to an error), without the overhead of a thrown exception. Thus, if you want to handle errors, passing a callback method is the way to do it.

Upvotes: 1

Neenad
Neenad

Reputation: 911

Its because of the Asynchronous nature of Javascript that the code will not catch the exception you are throwing. The res.sendFile is executed outside the scope of try block and the try block execution will be over after the call to res.sendFile method.

That is the reason why it is always advised to use the callback mechanism with err object as the first argument to the callback and you can check that first before proceeding

res.sendFile(path, function (e) { // check the error first // then procedd with the execution });

Upvotes: 2

sempasha
sempasha

Reputation: 623

Due to documentation res.sendFile is async function, so try/catch won't work in this case. If you want to handle res.sendFile result you must pass callback as last argument.

res.sendFile(path, function (e) {
  if (e) {
    if (e.code === 'ENOENT') {
      res.send('placeholder');
    } else {
      throw e;
    }
  }
});

Upvotes: 3

Related Questions