Error Handling: Keeping Your Code Safe!

Error Handling: Keeping Your Code Safe!

Imagine you’re a lifeguard, responsible for watching over swimmers in a pool. If someone gets into trouble, it’s your job to dive in and save them before things get worse. In programming, errors are like troubled swimmers. If left unchecked, they can cause your entire program to crash. But with the right tools and techniques, you can catch these errors and handle them before they cause serious damage.

In this article, we’ll explore error handling in JavaScript—the tools and methods you can use to catch and respond to errors in your code. By the end, you’ll understand how to keep your programs running smoothly, even when things go wrong.


Types of Errors in JavaScript

Errors in JavaScript come in different forms, and it’s important to know the difference between them so you can handle each one appropriately. Generally, errors fall into three categories:

  1. Syntax Errors: These occur when you write code that doesn’t follow the rules of JavaScript syntax.

  2. Runtime Errors: These happen when your code is syntactically correct but fails during execution, often due to invalid operations.

  3. Logical Errors: These occur when your code runs without crashing, but it doesn’t produce the expected results.

Let’s break down each type in more detail.


Syntax Errors

A syntax error happens when there is a mistake in how the code is written, such as missing a bracket or using incorrect syntax. These errors prevent the program from running.

Example:

let x = 10
console.log(x;  // Syntax error: missing closing parenthesis

Explanation:

  • The missing closing parenthesis causes a syntax error, and JavaScript will not execute the script until the issue is fixed.

Runtime Errors

A runtime error occurs when the code is correct in structure but fails during execution, often due to invalid operations like trying to access a variable that doesn’t exist.

Example:

let x = 10;
console.log(y); // ReferenceError: y is not defined

Explanation:

  • In this case, the variable y is not defined, causing a ReferenceError at runtime.

Logical Errors

A logical error happens when your code executes without crashing, but it produces incorrect or unexpected results due to faulty logic in your code.

Example:

let x = 5;
let y = 10;
let result = x - y; // Logical error: should be x + y
console.log(result); // Output: -5 (but the expected output was 15)

Explanation:

  • Although the code runs without errors, the logic is wrong, leading to incorrect results. The expected operation was addition, but subtraction was mistakenly used.

Flowchart: Syntax vs. Runtime vs. Logical Errors

Let’s visualize the flow of how different errors occur:

           [ Write Code ]
                |
         [ Syntax Check ]
                |
      Syntax Error? ----> [ Fix Syntax ]
                |
     [ Execute Code ]
                |
     Runtime Error? ----> [ Handle Runtime Error ]
                |
   [ Expected Output? ]
                |
   Logical Error? ----> [ Debug Logic ]
                |
        [ Successful Program ]

This flowchart demonstrates how errors can occur at different stages of the programming process and how they should be addressed.


Using Try/Catch for Error Handling

Now that we’ve identified the different types of errors, let’s talk about how to catch and handle them. In JavaScript, we use the try/catch block to catch errors that occur during the execution of our code. Think of this as your lifeguard tool for catching and handling troubled code.

The try/catch statement allows you to test a block of code and catch any errors that occur within that block.

The Structure of Try/Catch

javascriptCopy codetry {
    // Code that may throw an error
} catch (error) {
    // Code to handle the error
}

Here’s how it works:

  • try block: This contains the code you want to execute. If an error occurs, the execution stops and control is passed to the catch block.

  • catch block: This block handles the error, allowing you to respond to it (e.g., logging the error, showing a user-friendly message, or retrying the operation).


Code Snippet: Basic Try/Catch Example

Let’s see a basic example of how try/catch works:

try {
    let result = 10 / 0; // This will not throw an error
    console.log(result); // Output: Infinity
    let data = JSON.parse('{"name": "John"'); // SyntaxError: Unexpected end of JSON
} catch (error) {
    console.log("An error occurred: " + error.message);
}

Explanation:

  • In this example, the try block attempts to parse an invalid JSON string, which throws a SyntaxError.

  • The catch block catches the error and logs a message: "An error occurred: Unexpected end of JSON".

Without the try/catch block, this error would cause the program to crash. With try/catch, you can gracefully handle the error without stopping the entire program.


Throwing Custom Errors

Sometimes, you’ll want to create your own errors to signal when something goes wrong in your program. This is where throwing custom errors comes in handy. You can use the throw statement to generate an error, which can then be caught by a try/catch block.

Throwing an Error

You can throw an error with any message you want, signaling that something has gone wrong in your code:

function checkAge(age) {
    if (age < 18) {
        throw new Error("You must be at least 18 years old.");
    } else {
        console.log("Access granted.");
    }
}

try {
    checkAge(16);
} catch (error) {
    console.log(error.message); // Output: You must be at least 18 years old.
}

Explanation:

  • In this example, if the user’s age is less than 18, a custom error is thrown.

  • The catch block captures the error and logs the custom message: "You must be at least 18 years old."


Protecting Your Code with Try/Catch

In this part, we’ve introduced the types of errors in JavaScript and learned how to handle them using the try/catch mechanism. Like a lifeguard watching over swimmers, try/catch allows you to catch errors before they cause your program to crash and handle them gracefully.

In the next part, we’ll explore more advanced error-handling techniques, including custom error handling and building an application with robust error handling.


Throwing Custom Errors

Earlier, we introduced the idea of catching errors using try/catch. But sometimes, you might want to throw your own errors when specific conditions in your program aren’t met. By throwing custom errors, you give yourself more control over what goes wrong and how it should be handled.

Custom Error Types

While you can throw a generic error using new Error(), JavaScript also allows you to create specialized errors that help clarify the kind of issue that occurred. Some of the built-in error types include:

  • TypeError: Thrown when a value is not of the expected type.

  • ReferenceError: Thrown when a variable is not found.

  • SyntaxError: Thrown when code has invalid syntax.

  • RangeError: Thrown when a number is out of the expected range.

You can also create your own custom error messages to signal specific issues in your code.


Code Snippet: Creating Custom Error Messages

Here’s an example of how you can create a custom error based on specific conditions:

processOrder(item, quantity) {
    if (quantity < 0) {
        throw new RangeError("Quantity cannot be negative.");
    }
    if (!item) {
        throw new ReferenceError("Item not found.");
    }

    console.log(`Processing order for ${quantity} ${item}(s).`);
}

try {
    processOrder("apple", -5);
} catch (error) {
    console.log(`${error.name}: ${error.message}`); // Output: RangeError: Quantity cannot be negative.
}

Explanation:

  • We’ve used the throw statement to manually trigger a RangeError when the quantity is negative and a ReferenceError when the item is missing.

  • The catch block handles the error and logs the error type (error.name) and message (error.message).


Challenge — Build an App with Robust Error Handling

Now that we’ve learned how to handle errors and throw custom errors, it’s time to apply these skills by building a small app that demonstrates robust error handling. In this challenge, you’ll build an app that accepts user input, processes it, and handles any errors that occur gracefully.

Challenge Instructions

  1. Create a simple user input form that asks the user for a number.

  2. Use try/catch to handle any errors that might occur when processing the input.

  3. Throw custom errors if the input is invalid, such as if the input is not a number or is out of range.

  4. Provide helpful error messages to the user.

Here’s an example of what the app might look like:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Error Handling App</title>
</head>
<body>
    <h1>Enter a Number</h1>
    <input type="text" id="userInput" placeholder="Enter a number">
    <button onclick="processInput()">Submit</button>
    <p id="message"></p>

    <script>
        function processInput() {
            let input = document.getElementById("userInput").value;
            let message = document.getElementById("message");

            try {
                if (isNaN(input)) {
                    throw new TypeError("Input must be a number.");
                }

                let number = parseInt(input);

                if (number < 0 || number > 100) {
                    throw new RangeError("Number must be between 0 and 100.");
                }

                message.innerHTML = `You entered: ${number}`;
            } catch (error) {
                message.innerHTML = `${error.name}: ${error.message}`;
            }
        }
    </script>
</body>
</html>

Code Explanation

  • The user enters a value in the input field, and when they click the button, the processInput() function is executed.

  • We check if the input is a number using isNaN(). If not, a TypeError is thrown.

  • We then check if the number is within the valid range (0–100). If not, a RangeError is thrown.

  • The try/catch block ensures that any errors that occur are caught and displayed to the user, allowing the program to continue without crashing.


Enhancing Code Safety with Error Handling

By implementing proper error handling, you significantly improve the resilience of your code. Instead of letting errors crash your entire program, you can catch and respond to them gracefully, providing users with helpful messages or retrying operations when necessary.

Key Takeaways:

  1. Use try/catch to prevent program crashes: When you expect an operation might fail, use try/catch to gracefully handle errors and keep your program running.

  2. Throw custom errors to signal specific problems: Instead of letting your code fail silently or produce confusing results, throw custom errors with meaningful messages.

  3. Provide helpful feedback to users: When errors occur in user-facing applications, provide clear messages to help users understand what went wrong and how to fix it.


Stay tuned for JSON Journeys!

In the next article, we’ll embark on a new journey—exploring JSON (JavaScript Object Notation). You’ll learn how to work with JSON data, parse and stringify it, and use it for APIs and web development. Don’t miss this adventure into the world of data!