Unhandled promise rejections

Loading

Unhandled Promise Rejections in JavaScript: Causes, Consequences, and Solutions

Step 1: Understanding Promises in JavaScript

A Promise in JavaScript is an object that represents the eventual completion (or failure) of an asynchronous operation. It can be in one of three states:

  • Pending: The initial state, neither fulfilled nor rejected.
  • Fulfilled: The operation was successful.
  • Rejected: The operation failed.

Basic Syntax of a Promise

const myPromise = new Promise((resolve, reject) => {
  let success = true; // Change to false to test rejection
  if (success) {
    resolve("Operation was successful!");
  } else {
    reject("Something went wrong!");
  }
});

// Handling the Promise
myPromise
  .then(result => console.log(result)) // Handles success
  .catch(error => console.error(error)); // Handles failure

✅ This correctly handles both success and failure cases using .then() and .catch().


Step 2: What is an Unhandled Promise Rejection?

An Unhandled Promise Rejection occurs when a Promise rejects, but there is no .catch() or error-handling mechanism in place to handle the rejection.

Example of an Unhandled Promise Rejection

const myPromise = new Promise((resolve, reject) => {
  reject("Error occurred!"); // The promise is rejected
});

// No `.catch()` is used, so the rejection is unhandled!

🚨 This will cause an UnhandledPromiseRejectionWarning in Node.js or an error in the browser’s developer console.


Step 3: Why Are Unhandled Promise Rejections a Problem?

  1. Silent Failures: If an error is not handled, it can cause unexpected behavior without visible errors.
  2. Hard to Debug: When unhandled, errors might surface later in unrelated parts of your application.
  3. Crashes in Node.js: Starting from Node.js v15, unhandled promise rejections terminate the process.

Step 4: Real-World Scenarios of Unhandled Promise Rejections

1. Forgetting to Attach .catch()

fetch("https://api.example.com/data")
  .then(response => response.json()) // ✅ Success case
  // ❌ No `.catch()` to handle rejection

Fix: Always Attach .catch()

fetch("https://api.example.com/data")
  .then(response => response.json())
  .catch(error => console.error("Fetch failed:", error));

2. Using async/await Without Try-Catch

async function fetchData() {
  let response = await fetch("https://api.example.com/data"); // ❌ Can fail!
  let data = await response.json();
  console.log(data);
}

fetchData(); // If fetch fails, the rejection is unhandled!

🚨 This will result in an Unhandled Promise Rejection if fetch() fails.

Fix: Use Try-Catch Block

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

fetchData();

3. Returning a Rejected Promise Without Handling

function riskyOperation() {
  return new Promise((resolve, reject) => {
    reject("Operation failed!");
  });
}

riskyOperation(); // ❌ No `.catch()` attached

Fix: Attach .catch() or use async/await with try-catch

riskyOperation().catch(error => console.error("Handled:", error));

or

async function handleRiskyOperation() {
  try {
    await riskyOperation();
  } catch (error) {
    console.error("Caught error:", error);
  }
}
handleRiskyOperation();

Step 5: Handling Unhandled Promise Rejections Globally

1. Using process.on("unhandledRejection") in Node.js

process.on("unhandledRejection", (reason, promise) => {
  console.error("Unhandled Rejection:", reason);
});

✅ This ensures that even if a Promise rejection is not handled locally, it gets logged and does not crash the application.


2. Using window.addEventListener("unhandledrejection") in Browsers

window.addEventListener("unhandledrejection", event => {
  console.error("Unhandled promise rejection:", event.reason);
});

✅ This captures all unhandled rejections in client-side JavaScript.


Step 6: Best Practices to Avoid Unhandled Promise Rejections

Best PracticeExample
Always attach .catch() to promisesmyPromise.catch(error => console.error(error));
Use try-catch in async functionstry { await fetchData(); } catch (error) { console.error(error); }
Use process.on("unhandledRejection") in Node.jsprocess.on("unhandledRejection", reason => console.error(reason));
Use window.addEventListener("unhandledrejection") in browserswindow.addEventListener("unhandledrejection", event => console.error(event.reason));
Use Promise.allSettled() for multiple promisesPromise.allSettled([p1, p2, p3]).then(results => console.log(results));

Step 7: Summary

Unhandled Promise Rejections occur when a rejected promise is not properly handled.
🚨 This can lead to silent failures, crashes, and hard-to-debug issues.
💡 Always use .catch(), try-catch blocks, and global rejection handlers (process.on() and window.addEventListener()).


Would you like a debugging checklist or sample logging utility for tracking Promise rejections?

Leave a Reply

Your email address will not be published. Required fields are marked *