Home Python C Language C ++ HTML 5 CSS Javascript Java Kotlin SQL DJango Bootstrap React.js R C# PHP ASP.Net Numpy Dart Pandas Digital Marketing

Understanding Callbacks vs. Promises in JavaScript


In JavaScript, both callbacks and promises are used to handle asynchronous operations, such as fetching data from a server, reading files, or waiting for a timer. While both techniques achieve similar results, they have different characteristics and usage patterns. In this article, we'll explore the differences between callbacks and promises, along with examples of how each one works.

1. What is a Callback?

A callback is a function passed into another function as an argument, which is then executed after the completion of an asynchronous operation. Callbacks are widely used in JavaScript for handling events and asynchronous code execution.

Here’s an example of using a callback to simulate an asynchronous operation:

          function fetchData(callback) {
              setTimeout(function() {
                  console.log("Data fetched");
                  callback();  // Executes the callback function after the task is done
              }, 2000);
          }

          function processData() {
              console.log("Processing data...");
          }

          fetchData(processData);
          // Output:
          // Data fetched
          // Processing data...
      

In this example, fetchData simulates an asynchronous operation using setTimeout, and once the data is "fetched," it calls the processData function.

2. Callback Hell

Callbacks, when used in complex scenarios with multiple asynchronous operations, can lead to "callback hell" or "pyramid of doom." This occurs when callbacks are nested within other callbacks, making the code difficult to read and maintain.

          function firstTask(callback) {
              setTimeout(function() {
                  console.log("First task done");
                  callback();
              }, 1000);
          }

          function secondTask(callback) {
              setTimeout(function() {
                  console.log("Second task done");
                  callback();
              }, 1000);
          }

          function thirdTask() {
              setTimeout(function() {
                  console.log("Third task done");
              }, 1000);
          }

          firstTask(function() {
              secondTask(function() {
                  thirdTask();
              });
          });
          // Output:
          // First task done
          // Second task done
          // Third task done
      

In this example, each task is performed sequentially, but the nested structure of callbacks makes the code harder to follow and maintain. This is a common issue with callbacks in complex asynchronous workflows.

3. What is a Promise?

A promise is an object that represents the eventual completion or failure of an asynchronous operation. Unlike callbacks, promises allow for cleaner, more readable code by chaining multiple operations using .then() and handling errors with .catch().

Here’s an example of using a promise to handle the same operation as the previous callback example:

          function fetchData() {
              return new Promise(function(resolve, reject) {
                  setTimeout(function() {
                      console.log("Data fetched");
                      resolve();  // The promise is resolved after the data is fetched
                  }, 2000);
              });
          }

          function processData() {
              console.log("Processing data...");
          }

          fetchData().then(processData);
          // Output:
          // Data fetched
          // Processing data...
      

In this example, the fetchData function returns a promise. Once the data is fetched, the promise is resolved, and the processData function is called. This approach makes the code more readable compared to using nested callbacks.

4. Chaining Promises

One of the biggest advantages of promises over callbacks is that they can be chained. This allows you to execute multiple asynchronous operations sequentially, in a more organized and readable way.

          function firstTask() {
              return new Promise(function(resolve) {
                  setTimeout(function() {
                      console.log("First task done");
                      resolve();
                  }, 1000);
              });
          }

          function secondTask() {
              return new Promise(function(resolve) {
                  setTimeout(function() {
                      console.log("Second task done");
                      resolve();
                  }, 1000);
              });
          }

          function thirdTask() {
              return new Promise(function(resolve) {
                  setTimeout(function() {
                      console.log("Third task done");
                      resolve();
                  }, 1000);
              });
          }

          firstTask()
              .then(secondTask)
              .then(thirdTask);
          // Output:
          // First task done
          // Second task done
          // Third task done
      

In this example, the tasks are executed sequentially, but the code is much cleaner than the nested callback approach. Each promise resolves before the next task is executed, and the flow is easy to follow.

5. Handling Errors with Promises

Promises provide a built-in way to handle errors using the .catch() method. This is especially useful for error handling in asynchronous operations.

          function fetchData(success) {
              return new Promise(function(resolve, reject) {
                  setTimeout(function() {
                      if (success) {
                          console.log("Data fetched");
                          resolve();
                      } else {
                          reject("Error: Data not found");
                      }
                  }, 2000);
              });
          }

          fetchData(true).then(function() {
              console.log("Processing data...");
          }).catch(function(error) {
              console.log(error);  // Handles errors if the promise is rejected
          });

          fetchData(false).then(function() {
              console.log("Processing data...");
          }).catch(function(error) {
              console.log(error);  // Output: Error: Data not found
          });
      

In this example, fetchData returns a promise that resolves or rejects based on the success parameter. The .catch() method is used to handle errors when the promise is rejected.

6. Callbacks vs. Promises: Key Differences

Conclusion

Both callbacks and promises are essential for handling asynchronous operations in JavaScript. While callbacks are simple and effective for handling a single asynchronous task, promises provide a more flexible, readable, and error-resistant way to work with multiple asynchronous tasks. Understanding when to use each approach is crucial for writing efficient, maintainable JavaScript code.





Advertisement





Q3 Schools : India


Online Complier

HTML 5

Python

java

C++

C

JavaScript

Website Development

HTML

CSS

JavaScript

Python

SQL

Campus Learning

C

C#

java