Contents

Error Handling

Error handling in JavaScript ensures that your code gracefully deals with unexpected situations, such as invalid input or network issues, instead of breaking or causing unintended behavior. JavaScript provides a structured way to manage errors using try…catch, the ability to throw errors, and the option to create custom errors.

try...catch

The try…catch block is the fundamental construct for error handling in JavaScript. It allows you to “try” a block of code and “catch” any errors that occur, providing a way to handle those errors gracefully.

Syntax:
				
					try {
  // Code that may throw an error
} catch (error) {
  // Code to handle the error
}

				
			
  • try block: Contains the code that might throw an error.
  • catch block: Contains the code that runs if an error occurs in the try block. The error object provides details about what went wrong.
 
Example: Basic try…catch
				
					try {
  let result = 10 / 0;
  console.log(result); // Infinity, no error here
  let person = undefined;
  console.log(person.name); // This will throw an error
} catch (error) {
  console.log("An error occurred:", error.message);
}

				
			
  • In this example, person.name throws an error because person is undefined. The catch block captures the error and logs a message instead of breaking the code.

 

1.1 finally Block

The finally block is an optional part of the try…catch construct. It will execute after the try and catch blocks, whether an error occurred or not.

				
					try {
  let result = 10 / 2;
  console.log(result);
} catch (error) {
  console.log("An error occurred:", error.message);
} finally {
  console.log("This will always run, regardless of errors.");
}

				
			

Throwing Errors

In JavaScript, you can manually throw errors using the throw statement. This is useful when you want to generate custom error messages based on specific conditions.

Syntax:
				
					throw new Error("Something went wrong!");

				
			
  • The throw keyword is used to raise an error, and the Error object is typically passed with a custom error message.
 
Example: Throwing Errors
				
					function divide(a, b) {
  if (b === 0) {
    throw new Error("Division by zero is not allowed.");
  }
  return a / b;
}

try {
  console.log(divide(10, 2)); // Output: 5
  console.log(divide(10, 0)); // This will throw an error
} catch (error) {
  console.log("Error:", error.message);
}

				
			
  • In this example, an error is thrown when the divisor b is 0, which is then caught and handled by the catch block.

Custom Errors

JavaScript allows you to create your own custom error classes by extending the built-in Error class. This can be useful when you want to differentiate between different types of errors in your application and provide more specific error messages.

3.1 Creating a Custom Error Class

To create a custom error, you extend the base Error class and add custom properties or methods if needed.

Example: Custom Error
				
					class ValidationError extends Error {
  constructor(message) {
    super(message); // Pass the message to the base Error class
    this.name = "ValidationError"; // Set the error name
  }
}

function validateUserInput(input) {
  if (!input || input.length < 5) {
    throw new ValidationError("Input must be at least 5 characters long.");
  }
  return input;
}

try {
  validateUserInput("abc"); // This will throw a ValidationError
} catch (error) {
  if (error instanceof ValidationError) {
    console.log(`Validation Error: ${error.message}`);
  } else {
    console.log(`General Error: ${error.message}`);
  }
}

				
			
  • ValidationError: This custom error class extends the built-in Error class and adds a custom error type for validation-related issues. The catch block can now distinguish between different types of errors.
 
3.2 Multiple Custom Errors

You can create multiple custom error classes to handle different types of errors more specifically.

				
					class AuthenticationError extends Error {
  constructor(message) {
    super(message);
    this.name = "AuthenticationError";
  }
}

class AuthorizationError extends Error {
  constructor(message) {
    super(message);
    this.name = "AuthorizationError";
  }
}

try {
  // Simulate an authentication error
  throw new AuthenticationError("User is not authenticated.");
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.log("Authentication Error:", error.message);
  } else if (error instanceof AuthorizationError) {
    console.log("Authorization Error:", error.message);
  } else {
    console.log("General Error:", error.message);
  }
}

				
			

Best Practices for Error Handling

  1. Handle Errors Gracefully: Always handle errors in a way that provides feedback to the user while keeping the application stable.
  2. Use Specific Errors: Use custom error classes to make your error handling more specific and readable.
  3. Don’t Catch Silent Errors: Avoid catching errors without any action or logging. Silent errors can make debugging difficult.
  4. Use finally for Cleanup: Always use the finally block to clean up resources, like closing a database connection or clearing timers, regardless of whether an error occurred.
  5. Throw Meaningful Errors: When throwing errors, provide meaningful messages that help developers understand the cause of the error.

Summary

Error handling in JavaScript allows you to manage unexpected issues during code execution, ensuring that your applications handle failures gracefully. The try…catch block is used to catch and handle errors, and you can manually throw errors when necessary. Creating custom errors by extending the Error class helps make error handling more specific and readable, allowing for fine-grained control over different types of errors. Proper error handling improves the robustness, maintainability, and user experience of your applications.