Exception Handling
Introduction
Exception handling is the process of handling errors and unexpected situations in a program. In JavaScript, exceptions are thrown when an error occurs or when a certain condition is not met.
Exception handling is important in JavaScript because it helps to prevent crashes and unexpected behavior in a program. It also helps to improve the user experience by providing useful error messages and handling errors in a graceful manner.
What is an Exception?
An exception is an error that occurs during the execution of a program. When an exception occurs, the program stops executing and the error is thrown. The error can be handled by the program, or it can be thrown to the calling function.
Why do we need Exception Handling?
Exceptions are designed to help programs gracefully handle unexpected situations. Instead of terminating the program when an error occurs, exceptions allow the program to recover from the error and continue executing. This is particularly useful in large and complex programs where errors are difficult to anticipate and diagnose.
We will learn more about how to handle exceptions in JavaScript in this doc
Error vs Exception
In programming, the terms "exception" and "error" are often used interchangeably, but they do have different meanings.
Error
An error is a problem with the code. It is a mistake that the programmer has made. For example, a syntax error is an error in the code that prevents the program from running.
Exception
An exception is a problem that occurs during the execution of a program. It is a situation that the programmer could not have anticipated. For example, a runtime error occurs when the program tries to access a variable that is not defined.
try...catch
The try...catch statement is used to handle exceptions in JavaScript. It allows you to define a block of code that will be executed if an exception is thrown. If an exception is thrown, the catch block will be executed.
try {
// code that may throw an exception
} catch (error) {
// code that will be executed if an exception is thrown
}
When an exception is thrown, the try block will stop executing and the catch block will be executed. The catch block will receive the exception as an argument. The argument is usually called error or e.
finally
The finally block is used to execute code after the try block has finished executing. It is executed regardless of whether an exception was thrown or not.
try {
// code that may throw an exception
} catch (error) {
// code that will be executed if an exception is thrown
} finally {
// code that will be executed after the try block has finished executing
}
throw
If there's an exception in the try block, the catch block will be executed. But what if we want to throw an exception manually? We can do that using the throw statement. The throw statement takes an error object as its parameter, which contains information about the exception.
When an exception is thrown, the try block will stop executing and the catch block will be executed. If the throw statement is used outside a try...catch block, the program will stop executing and the error will be thrown.
Example - Divide by Zero Error
function divide(x, y) {
if (y === 0) {
throw new Error("Cannot divide by zero.");
}
return x / y;
}
try {
let result = divide(10, 0);
console.log(result); // this line will not execute
} catch (error) {
console.log(error.message); // prints "Cannot divide by zero."
}
In the example above, the divide function throws an exception if the second argument is zero. The try...catch statement catches the exception and prints the error message.
Type of Exceptions
We can also throw any type of exception. Let's see most common types of exceptions in JavaScript.
Error
The Error object is the base object for all errors in JavaScript. It is used to represent errors that occur while executing a program.
try {
throw new Error("Something went wrong.");
} catch (error) {
console.log(error.message); // prints "Something went wrong."
}
SyntaxError
The SyntaxError object represents an error that occurs when the JavaScript engine encounters invalid syntax.
try {
throw new SyntaxError("Invalid syntax.");
} catch (error) {
console.log(error.message); // prints "Invalid syntax."
}
ReferenceError
The ReferenceError object represents an error that occurs when a non-existent variable is referenced.
try {
throw new ReferenceError("Variable is not defined.");
} catch (error) {
console.log(error.message); // prints "Variable is not defined."
}
TypeError
The TypeError object represents an error that occurs when a variable or parameter is not of a valid type.
try {
if (typeof x !== "number") {
throw new TypeError("Invalid type.");
}
} catch (error) {
console.log(error.message); // prints "Invalid type."
}
RangeError
The RangeError object represents an error that occurs when a number is outside the valid range.
try {
const x = 200;
if (x < 0 || x > 100) {
throw new RangeError("Number is out of range.");
}
} catch (error) {
console.log(error.message); // prints "Number is out of range."
}
URIError
The URIError object represents an error that occurs when a global URI handling function is used in a wrong way.
try {
if (decodeURI("%") === "%") {
throw new URIError("URI malformed");
}
} catch (error) {
console.log(error.message); // prints "URI malformed"
}
It's a standard practice to throw relevant exceptions in your code. For example, if you are writing a function that accepts a number as an argument, you should throw a TypeError exception if the argument is not a number.
Multiple catch blocks
JavaScript does not support multiple catch blocks for a single try block. However, you can use if statements to handle different types of exceptions.
For example, I want to write a function that checks if a person is old enough to vote. If the person is not old enough, I would like to throw an exception. I want to throw a different exception if the age is not a number.
Here is an example:
function checkAge(age) {
if (typeof age !== "number") {
throw new TypeError("Age must be a number.");
}
if (age < 18) {
throw new RangeError("Age must be at least 18.");
}
return age;
}
try {
checkAge(15); // 15 is under 18, so RangeError will be thrown
console.log("You are old enough to vote.");
} catch (error) {
// handle different types of exceptions
// In this example, RangeError condition will be executed
if (error instanceof TypeError) {
console.log(error.message); // prints "Age must be a number."
} else if (error instanceof RangeError) {
console.log(error.message); // prints "Age must be at least 18."
} else {
console.log(error.message); // prints "Unknown error."
}
}
Custom Exceptions
You can also create your own exceptions. You can create a custom exception by creating a new object that inherits from the Error object using constructor functions.
For example, I want to create a custom exception called CustomError where I also want to include the status code.
class CustomError extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
}
}
try {
throw new CustomError("Something went wrong.", 500);
} catch (error) {
console.log(error.message); // prints "Something went wrong."
console.log(error.statusCode); // prints 500
}
Summary
In this article, we learned about exceptions in JavaScript. We learned about the try...catch statement and how to throw exceptions manually using the throw statement. We also learned about the different types of exceptions in JavaScript and how to create custom exceptions.