topic: Javascript error handling best practices

Tags javascript

Errors are useful

There’s a reason why errors are in almost all if not all languages. They serve to indicate that something bad and unintended happens. They don’t exist to just be squashed or just logged.

Errors that occur usually stop and terminate the program. The most common way of handling errors in JavaScript is by using the try catch statement. This is used to try and gracefully handle the error or use info from the error to handle it accordingly.

try {
  // critical code that may fail goes here
} catch (error) {
  // - if an error occurs in the try the error is caught and made available here
  // - this is where you can verify certain errors, notify the user .etc.
}

Bad error handling

The following are examples of how tutorials/people handle errors:

  • just print errors
try {
  // code...
} catch (error) {
  console.log(error);
}
  • just print errors with a different colour
try {
  // code...
} catch (error) {
  console.error(error);
}
  • return errors
try {
  // code...
} catch (error) {
  return error;
}
  • catch expected errors just to re-throw them without added context
try {
  // code...
} catch (error) {
  throw new Error(error);
}
  • catch but ignore the caught errors
try {
  // code...
} catch (error) {
  throw new Error(
    "new error that may or may not be related to the caught error"
  );
}

When to catch errors

The rule of thumb is to catch errors where you can handle them effectively, this is usually on the UI layer of an application with consumer software. That can either be by using the information from the error thrown and letting a user know if they can do something about it or just re-throwing it with more context for the developers to know what happened.

Throwing custom errors

Throw custom errors when you know exactly what went wrong, or when you want to add more context to an existing error.

There are different kinds of syntax for throwing errors

just throwing a caught error or any type as an error

// BAD - because it misinterprets where the error occurred you can throw pretty much anything as an error
throw error;

throw "some error";

throw {};

using the error object:

// GOOD - because  it tells you exactly where the error occurred and the constructor takes in a message making it more predictable
throw new Error(error);

throw new Error("error message");

Resources


RAW CONTENT URL