Scalable Business for Startups

Get the oars in the water and start rowing. Execution is the single biggest factor in achievement so the faster and better your execution.

+91 9472774549 thebytemind@gmail.com Looking for collaboration for your next creative project?

Chapter 13: Error Handling and Debugging in JavaScript

In JavaScript, error handling and debugging are crucial for building robust applications. This chapter will guide you through various concepts and techniques to effectively manage errors and troubleshoot your code, from basic to advanced levels.

Table of Contents
  1. Understanding Errors in JavaScript
    • Types of Errors
    • Error Objects
  2. Error Handling Techniques
    • Using try...catch
    • Finally Block
    • Throwing Custom Errors
  3. Debugging Techniques
    • Using console Methods
    • Debugging with Developer Tools
    • Breakpoints and Watch Expressions
    • Inspecting Variables
  4. Advanced Error Handling
    • Asynchronous Error Handling
    • Promises and Async/Await
    • Global Error Handling
  5. Best Practices for Error Handling and Debugging
  6. Common Debugging Scenarios and Solutions
1. Understanding Errors in JavaScript
Types of Errors

JavaScript errors can be categorized into three main types:

  • Syntax Errors: Occur when the code is not well-formed.
  • // Example of a syntax error
    const x = ; // Missing value will throw a SyntaxError
  • Runtime Errors: Occur during the execution of the program.
  • // Example of a runtime error
    const y = null;
    console.log(y.toString()); // TypeError: Cannot read properties of null
  • Logical Errors: Occur when the code runs without throwing an error, but the output is not as expected.
  • // Example of a logical error
    function add(a, b) {
        return a - b; // Should be addition, not subtraction
    }
    console.log(add(2, 3)); // Outputs 1 instead of 5
Error Objects

JavaScript provides an Error object that contains information about the error that occurred.

try {
    throw new Error("Something went wrong!");
} catch (error) {
    console.error(error.message); // Outputs: Something went wrong!
}
2. Error Handling Techniques
Using try...catch

The try...catch statement allows you to test a block of code for errors.

try {
    // Code that may throw an error
    const result = riskyFunction();
    console.log(result);
} catch (error) {
    // Handle the error
    console.error("Error occurred:", error.message);
}
Finally Block

The finally block executes after the try and catch blocks, regardless of the outcome.

try {
    const data = JSON.parse("Invalid JSON");
} catch (error) {
    console.error("Parsing error:", error.message);
} finally {
    console.log("This will run regardless of the outcome.");
}
Throwing Custom Errors

You can throw custom errors to handle specific conditions.

function validateAge(age) {
    if (age < 18) {
        throw new Error("Age must be at least 18.");
    }
    return true;
}

try {
    validateAge(16);
} catch (error) {
    console.error(error.message); // Outputs: Age must be at least 18.
}
3. Debugging Techniques
Using console Methods

The console object provides various methods to assist in debugging.

console.log("Info message");
console.warn("Warning message");
console.error("Error message");
Debugging with Developer Tools

Most modern browsers come with built-in developer tools that allow you to inspect, debug, and profile your JavaScript code. You can access these tools by right-clicking on a webpage and selecting "Inspect."

Breakpoints and Watch Expressions

You can set breakpoints in your code to pause execution and inspect variables.

  1. Open Developer Tools (F12).
  2. Navigate to the "Sources" tab.
  3. Click on the line number where you want to set a breakpoint.
Inspecting Variables

While paused at a breakpoint, you can hover over variables to see their current values or use the console to evaluate expressions.

4. Advanced Error Handling
Asynchronous Error Handling

Handling errors in asynchronous code can be tricky. Here’s how to manage errors with Promises and Async/Await.

Using Promises:
function fetchData() {
    return new Promise((resolve, reject) => {
        // Simulating a network request
        setTimeout(() => {
            const error = false; // Change to true to simulate an error
            if (error) {
                reject(new Error("Network error"));
            } else {
                resolve("Data received");
            }
        }, 1000);
    });
}

fetchData()
    .then(data => console.log(data))
    .catch(error => console.error(error.message));
Using Async/Await:
async function getData() {
    try {
        const data = await fetchData();
        console.log(data);
    } catch (error) {
        console.error("Error:", error.message);
    }
}

getData();
Global Error Handling

You can set up a global error handler to catch unhandled errors.

window.onerror = function (message, source, lineno, colno, error) {
    console.error(`Global Error: ${message} at ${source}:${lineno}:${colno}`);
};
5. Best Practices for Error Handling and Debugging
  • Use descriptive error messages to make debugging easier.
  • Log errors with context information to understand what went wrong.
  • Avoid using empty catch blocks; handle errors appropriately.
  • Use finally for cleanup operations that should execute regardless of success or failure.
6. Common Debugging Scenarios and Solutions
Scenario: TypeError

You might encounter a TypeError when trying to access a property of undefined.

Solution:
const user = undefined;
console.log(user?.name); // Outputs: undefined, prevents TypeError
Scenario: Infinite Loops

Infinite loops can crash your browser.

Solution:
let i = 0;
while (i < 10) {
    console.log(i);
    i++; // Ensure that the loop will terminate
}
Conclusion

Effective error handling and debugging are essential skills for any JavaScript developer. By mastering these techniques, you can write more resilient code and quickly identify and fix issues as they arise. In the next chapter, we will delve into performance optimization techniques to enhance your JavaScript applications further.