Transform Callback Hell to Promise - Step-by-Step Guide | Javascript

ยท

2 min read

Transform Callback Hell to Promise - Step-by-Step Guide | Javascript

Certainly! Let's start with an example using callback hell and then refactor it step by step using Promises.

Example with Callback Hell:

// Assume we have three asynchronous operations: fetchData, process1, and process2

function fetchData(callback) {
  setTimeout(() => {
    console.log("Data fetched successfully!");
    callback(null, { data: "some data" });
  }, 1000);
}

function process1(data, callback) {
  setTimeout(() => {
    console.log("Processing step 1 completed!");
    callback(null, data + " processed");
  }, 1000);
}

function process2(data, callback) {
  setTimeout(() => {
    console.log("Processing step 2 completed!");
    callback(null, data + " processed again");
  }, 1000);
}

// Callback Hell
fetchData((err1, result1) => {
  if (err1) {
    console.error("Error fetching data:", err1);
    return;
  }

  process1(result1.data, (err2, result2) => {
    if (err2) {
      console.error("Error processing step 1:", err2);
      return;
    }

    process2(result2, (err3, result3) => {
      if (err3) {
        console.error("Error processing step 2:", err3);
        return;
      }

      console.log("Final result:", result3);
    });
  });
});

This is a classic example of callback hell. Asynchronous operations are nested inside each other, making the code hard to read and maintain.

Refactoring with Promises:

Now, let's refactor the code step by step using Promises.

  1. PromisifyfetchData:
function fetchDataPromise() {
  return new Promise((resolve, reject) => {
    fetchData((err, result) => {
      if (err) {
        reject(err);
      } else {
        resolve(result);
      }
    });
  });
}

Now, fetchDataPromise returns a Promise that resolves with the data.

  1. Promisifyprocess1:
function process1Promise(data) {
  return new Promise((resolve, reject) => {
    process1(data, (err, result) => {
      if (err) {
        reject(err);
      } else {
        resolve(result);
      }
    });
  });
}
  1. Promisifyprocess2:
function process2Promise(data) {
  return new Promise((resolve, reject) => {
    process2(data, (err, result) => {
      if (err) {
        reject(err);
      } else {
        resolve(result);
      }
    });
  });
}
  1. Using Promises:
// Refactored code using Promises
fetchDataPromise()
  .then((result1) => process1Promise(result1.data))
  .then((result2) => process2Promise(result2))
  .then((finalResult) => {
    console.log("Final result:", finalResult);
  })
  .catch((error) => {
    console.error("Error:", error);
  });

By using Promises, the code becomes more readable and avoids the callback hell structure. Each asynchronous operation is wrapped in a Promise, and the .then method is used to chain the operations together. The .catch method is used to handle errors at any step in the chain.

Buy Me A Coffee

Did you find this article valuable?

Support Revive Coding by becoming a sponsor. Any amount is appreciated!

ย