Error Handling

In JavaScript, error handling allows you to manage problems in your code gracefully. Instead of letting your program crash, you can handle errors and provide meaningful feedback to users or take corrective actions.

What are Errors?

Errors occur when something goes wrong in your code, such as:

  • Syntax Errors: Mistakes in the code structure.
  • Runtime Errors: Problems that happen while the code is running.
  • Logical Errors: The code runs but doesn’t produce the expected result.

Example of an Error:

Javascript
Copy
console.log(name); // ReferenceError: name is not defined

The try...catch Block

The try...catch block is used to handle errors. It allows you to "try" a block of code and "catch" any errors that occur.

Syntax:

Javascript
Copy
try {
  // Code that might throw an error
} catch (error) {
  // Code to handle the error
}

Example: Handling an Error

Javascript
Copy
try {
  let result = 10 / 0; // This doesn't throw an error, but imagine there's an issue
  console.log(result);
} catch (error) {
  console.log("An error occurred:", error.message);
}

Adding a finally Block

The finally block runs after try and catch, whether an error occurred or not. Use it for cleanup tasks like closing files or clearing variables.

Syntax:

Javascript
Copy
try {
  // Code that might throw an error
} catch (error) {
  // Code to handle the error
} finally {
  // Code that runs no matter what
}

Example:

Javascript
Copy
try {
  let result = 5 + undefinedVariable; // Throws an error
} catch (error) {
  console.log("Error:", error.message);
} finally {
  console.log("Execution complete.");
}
// Outputs:
// Error: undefinedVariable is not defined
// Execution complete.

Throwing Your Own Errors

You can use the throw keyword to create your own errors when specific conditions are met.

Syntax:

Javascript
Copy
throw new Error("Custom error message");

Example: Throwing an Error

Javascript
Copy
function divide(a, b) {
  if (b === 0) {
    throw new Error("Division by zero is not allowed.");
  }
  return a / b;
}

try {
  console.log(divide(10, 0));
} catch (error) {
  console.log("Caught an error:", error.message);
}

Error Object

When an error occurs, JavaScript creates an Error object with details about the error. Common properties include:

  • name: The type of error (e.g., ReferenceError).
  • message: A description of what went wrong.
  • stack: A trace of where the error occurred.

Example: Error Object

Javascript
Copy
try {
  let result = unknownVariable + 1; // Throws a ReferenceError
} catch (error) {
  console.log("Error Name:", error.name);    // Outputs: ReferenceError
  console.log("Error Message:", error.message); // Outputs: unknownVariable is not defined
}

Types of Errors in JavaScript

a) SyntaxError

Occurs when the code violates JavaScript syntax rules.

Javascript
Copy
try {
  eval("console.log('Hello"); // Missing closing quote
} catch (error) {
  console.log(error.name); // Outputs: SyntaxError
}

b) ReferenceError

Occurs when accessing a variable that hasn't been declared.

Javascript
Copy
try {
  console.log(x); // x is not defined
} catch (error) {
  console.log(error.name); // Outputs: ReferenceError
}

c) TypeError

Occurs when a variable or parameter isn’t of a valid type.

Javascript
Copy
try {
  null.toString(); // You can't call a method on null
} catch (error) {
  console.log(error.name); // Outputs: TypeError
}

d) RangeError

Occurs when a value is out of an allowed range.

Javascript
Copy
try {
  let num = Number.MAX_VALUE;
  num.toExponential(500); // Too many decimal places
} catch (error) {
  console.log(error.name); // Outputs: RangeError
}

Best Practices for Error Handling

1. Use Specific Error Messages: Provide meaningful messages when throwing errors.

Javascript
Copy
if (!username) throw new Error("Username is required.");

2. Avoid Catch-All Blocks: Handle specific errors separately if needed.

Javascript
Copy
try {
  // Code
} catch (error) {
  if (error.name === "TypeError") {
    console.log("Handle type errors here.");
  } else {
    console.log("General error handling.");
  }
}

3. Don't Suppress Errors: Always log or act on errors; don't leave the catch block empty.

4. Use finally for Cleanup: Use the finally block to release resources, such as closing a database connection.

Real-World Example: User Input Validation

Example: Validating a Form

Javascript
Copy
function validateAge(age) {
  if (isNaN(age)) {
    throw new Error("Age must be a number.");
  }
  if (age < 0 || age > 120) {
    throw new Error("Age must be between 0 and 120.");
  }
  console.log("Valid age:", age);
}

try {
  validateAge(25); // Valid
  validateAge("abc"); // Invalid
} catch (error) {
  console.log("Validation Error:", error.message);
}

Async Error Handling

When working with asynchronous code (e.g., fetch() or async/await), errors can also occur. Use try...catch for error handling in asynchronous functions.

Example: Handling Errors in Async Code

Javascript
Copy
async function fetchData() {
  try {
    let response = await fetch("https://api.example.com/data");
    if (!response.ok) {
      throw new Error("Network response was not ok");
    }
    let data = await response.json();
    console.log(data);
  } catch (error) {
    console.log("Fetch Error:", error.message);
  }
}

fetchData();