Error Handling

  • This lesson explains structured error handling in JavaScript.
  • Introduction to Error Handling in Asynchronous JavaScript

    In real-world JavaScript applications, especially when working with:

    • APIs

    • Servers

    • Databases

    • Timers

    • Promises

    errors are unavoidable.

    If errors are not handled properly:

    • Application may crash

    • Data may be lost

    • Users may see blank screens

    • Debugging becomes difficult

    Asynchronous JavaScript requires special techniques for error handling, because errors do not always behave the same way as synchronous code.

    What Is an Error ?

    An error is a situation where JavaScript cannot execute code correctly due to:

    • Invalid logic

    • Missing data

    • Network failure

    • Server issues

    • Unexpected conditions

    Example:

    console.log(a);

    If a is not defined, JavaScript throws an error.

    Why Error Handling Is Critical in Async Code

    In synchronous code:

    • Errors can be caught easily using try...catch

    In asynchronous code:

    • Errors may occur later

    • Errors may happen outside the main execution flow

    • Errors must be handled differently

    Types of Errors in Async JavaScript

    Common async errors include:

    • Network errors

    • Promise rejections

    • API failures

    • Timeout issues

    • Invalid responses

    • JSON parsing errors

    Error Handling with Callbacks 

    Problem with Callbacks

Error Handling in Asynchronous JavaScript using Callbacks

Handles async errors using a callback with an error-first approach.

function getData(callback) {
  setTimeout(() => {
    callback("Error occurred", null);
  }, 1000);
}

getData(function (error, data) {
  if (error) {
    console.log(error);
  } else {
    console.log(data);
  }
});
  • Problems:

    • Error handling logic mixed with main logic

    • Code becomes hard to read

    • Leads to callback hell

    Error Handling with Promises

    Promises provide a cleaner way to handle async errors.

    Handling Errors Using .catch()

Error Handling using Promises in JavaScript

Handles errors in a Promise using .catch() when the Promise is rejected.

let promise = new Promise((resolve, reject) => {
  reject("Something went wrong");
});

promise
  .then(result => {
    console.log(result);
  })
  .catch(error => {
    console.log(error);
  });

  • If a promise is rejected, .catch() handles the error.

    Important Rule

    Any error inside a promise automatically goes to .catch()


Handling Exceptions in Promises

Automatically catches thrown errors inside a Promise using .catch().

new Promise((resolve, reject) => {
  throw new Error("Failure");
})
.catch(error => {
  console.log(error.message);
});

Error Handling in Promise Chaining

Catches errors from any step in a Promise chain using a single .catch() block.

fetchData()
  .then(data => {
    return processData(data);
  })
  .then(result => {
    console.log(result);
  })
  .catch(error => {
    console.log("Error:", error);
  });
    • One .catch() can handle errors from the entire chain

    • Prevents application crash

    What Happens Without .catch()

    fetchData()

      .then(data => {

        console.log(data);

      });

    If an error occurs:

    • Unhandled promise rejection

    • Application may break

    • Console warnings appear

    Error Handling with async and await

    async/await makes async code look synchronous, but error handling must still be done carefully.

    Using try...catch with Async Code

Error Handling with Async/Await

Uses try...catch to handle errors in asynchronous code with async/await.

async function getUserData() {
  try {
    let response = await fetch("https://api.example.com/user");
    let data = await response.json();
    console.log(data);
  } catch (error) {
    console.log("Error:", error);
  }
}

getUserData();
  • Why try...catch Works Here

    • await pauses execution

    • Rejected promises throw errors

    • catch block captures them

    Handling Network Errors vs API Errors

Checking HTTP Response Status in Async/Await

Validates API response status and throws an error if the request fails, handled using try...catch.

async function fetchData() {
  try {
    let response = await fetch("https://api.example.com/data");

    if (!response.ok) {
      throw new Error("HTTP Error: " + response.status);
    }

    let data = await response.json();
    console.log(data);
  } catch (error) {
    console.log("Fetch failed:", error.message);
  }
}

Handling Multiple Async Operations with Promise.all

Executes multiple async tasks in parallel and handles errors if any request fails.

async function loadAll() {
  try {
    let [user, posts] = await Promise.all([
      fetchUser(),
      fetchPosts()
    ]);

    console.log(user, posts);
  } catch (error) {
    console.log("One of the requests failed");
  }
}
  • If any promise fails, control goes to catch.

    Common Async Error Handling Mistakes

    Mistake 1: Using try...catch Without await

    try {

      fetchData();

    } catch (error) {

      console.log(error);

    }

    This will NOT catch async errors.

    Correct way:

    await fetchData();

    Mistake 2: Forgetting .catch()

    Unhandled promise rejections can crash applications.

    Mistake 3: Silent Errors

    catch (error) {}

    Always log or handle errors meaningfully.

    Best Practices for Async Error Handling

    • Always handle promise rejections

    • Use try...catch with async/await

    • Validate API responses

    • Log errors clearly

    • Show user-friendly messages

    • Avoid empty catch blocks

    • Clean up resources when errors occur

User-Friendly Error Handling in Async Operations

Provides a simple user-friendly message instead of exposing technical errors during failures.

async function loginUser() {
  try {
    let response = await fetch("/login");

    if (!response.ok) {
      throw new Error("Login failed");
    }

    console.log("Login successful");
  } catch (error) {
    console.log("Please try again later");
  }
}
  • Users see friendly messages, developers see logs.

    Error Handling Strategy

    1. Detect error early

    2. Handle error gracefully

    3. Log error for debugging

    4. Prevent app crash

    5. Inform user properly