Handling errors
JavaScript errors can occur for various reasons, such as incorrect syntax, runtime issues, or unexpected data. When an error occurs, JavaScript throws an exception, which can interrupt the normal flow of your program.
Common Types of Errors
-
Syntax Errors: These occur when there’s a mistake in the code structure. The interpreter can’t understand the script due to a typo or misplaced character.
-
Runtime Errors: These happen during the execution of the code and are often caused by unexpected conditions, like dividing by zero or trying to access an undefined variable or any other custom defined errors as we will see in this post.
-
Logic Errors: These are the trickiest to catch. Your code runs without any error, but it doesn’t produce the expected result due to a flaw in the algorithm or logic.
Throwing an Error
Errors can be thrown by the application itself but we can also do it whenever we want using throw
keyword. For this we can use built in Error
class but first we need to instantiate it so our full error throwing looks like throw new Error(<message>)
.
const user = { name: "John", age: 17 };
const canVote = function (user) {
const minimumAge = 18;
if (user.age < minimumAge) {
throw new Error(`User ${user.name} is below ${minimumAge} and can't vote.`);
}
};
canVote(user); // throws an error
/*
Uncaught Error: User John is below 18 and can't vote.
at canVote (<anonymous>:6:11)
at <anonymous>:12:1
*/
Using try
, catch
, and finally
JavaScript provides a powerful mechanism for handling errors using the try
, catch
, and finally
blocks.
- The
try
block contains the code that might throw an exception. - If an exception occurs, the
catch
block is executed, allowing you to handle the error gracefully. - The
finally
block is optional and executes whether an exception was thrown or not.
try {
// ...
} catch (error) {
// Handle the exception
console.error("An error occurred:", error.message);
} finally {
}
Creating Our Own Errors
We can create our own errors by extending previously mentioned Error
class. Error
class has 3 different properties (name
,message
and stack
) that we can change in our child error.
class YearError extends Error {
constructor(message) {
super(message);
this.name = "YearError";
}
}
const user = { name: "John", age: 17 };
const canVote = function (user) {
const minimumAge = 18;
if (user.age < minimumAge) {
throw new YearError(
`User ${user.name} is below ${minimumAge} and can't vote.`,
);
}
};
canVote(user); // throws an error
/*
Uncaught YearError: User John is below 18 and can't vote.
at canVote (<anonymous>:13:11)
at <anonymous>:19:1
*/
Logging and Debugging
Logging is a crucial aspect of error handling. Utilize console.log()
or other logging mechanisms to track the flow of your code and identify potential issues.
try {
// Code that might throw an exception
// ...
} catch (error) {
// Log the error for debugging
console.error("An error occurred:", error);
}
What Now?
Now you have even more control over your code handling and execution. Try and make an if else
statement in the catch
to execute different code depending on what error was thrown.