In the previous section, we learned how the Try/Catch statement helps us handle errors gracefully. Now, let’s dive deeper into how we can throw and handle our own errors in JavaScript. Throwing errors manually gives us more control over how and when an error should occur.
When we say we are throwing an error, it means we are intentionally creating an error when something unexpected happens in our code. For example, if a user enters an invalid value or a condition we expect isn't met, we can throw an error to alert the program that something went wrong.
JavaScript will then stop executing the code at the point where the error is thrown and look for a Catch block to handle it. This is where the Try/Catch structure comes in handy because the catch block can take care of what to do when that error happens.
To throw an error in JavaScript, we use the throw
keyword followed by the new Error()
function. This creates a new error object with a message describing what went wrong. Here's an example:
function checkAge(age) {
if (age < 0) {
throw new Error('Age cannot be negative'); // Throwing an error with a custom message
}
return 'Valid age: ' + age;
}
try {
console.log(checkAge(-5)); // This will throw an error because age is negative
} catch (error) {
console.log('Error:', error.message); // Handling the error
}
In this example, the checkAge
function checks if the age is a negative number. If it is, we throw an error using throw new Error()
with a custom message: "Age cannot be negative". When this happens, the code inside the try
block will stop running, and the control moves to the catch
block, where the error is handled.
You might be wondering, why would we throw errors ourselves? Here are some reasons:
By throwing errors where something goes wrong, you ensure that your program doesn't continue running with incorrect data or in an unexpected state. Instead, you can handle the error and take the appropriate action, such as showing an error message to the user or logging the issue for debugging.
While JavaScript provides some built-in errors (like TypeError
, ReferenceError
, etc.), you can throw custom errors by providing your own messages. This makes it easier to understand what went wrong. Here’s an example:
function checkEmail(email) {
if (!email.includes('@')) {
throw new Error('Invalid email format'); // Custom error message for invalid email
}
return 'Valid email: ' + email;
}
try {
console.log(checkEmail('invalidEmail.com')); // This will throw an error
} catch (error) {
console.log('Error:', error.message); // Handling the error
}
In this example, the checkEmail
function checks if the email contains an "@" symbol. If not, it throws a custom error: "Invalid email format". The catch
block then handles that error by printing the error message.
Once an error is thrown, we need to handle it in the Catch block. Handling errors means deciding what to do when something goes wrong. For example:
Let’s see how handling errors works inside a try
and catch
block. We can use the catch block to do something when an error happens:
try {
const userInput = 'invalidEmail.com';
console.log(checkEmail(userInput)); // Throws error
} catch (error) {
// Handling the error
console.log('An error occurred:', error.message);
// You can show a user-friendly message here, like:
console.log('Please enter a valid email address.');
}
In this example, if the user enters an invalid email, the catch
block will log the error message and provide a user-friendly message like "Please enter a valid email address."
By throwing and handling errors, you gain more control over how your code behaves when something unexpected happens. This ensures that your program doesn’t break down when an error occurs, and you can take the appropriate action to handle it. Whether you are validating user input, making network requests, or debugging your code, throwing and catching errors is a powerful tool to make your JavaScript programs more reliable.