DEV Community

Cover image for Asynchronous Programming in JavaScript: The Role of Callbacks Explained
Nishanthan K
Nishanthan K

Posted on

Asynchronous Programming in JavaScript: The Role of Callbacks Explained

Asynchronous Programming

  • Asynchronous programming in JavaScript allows the execution of tasks without blocking the main thread, which is essential for handling time-consuming operations (like fetching data from an API or reading a file) without freezing the user interface.
  • JavaScript is single-threaded, meaning it can only execute one task at a time. However, with asynchronous programming, it can delegate long-running tasks to the browser or Node.js environment, allowing the main thread to keep running while waiting for the tasks to finish.

Here are the key concepts:

Callbacks

  • A function passed as an argument to another function that gets executed once the task is completed. However, it can lead to "callback hell," where nested callbacks make the code hard to read and maintain.
setTimeout(() => {
  console.log("Task completed!");
}, 1000);
Enter fullscreen mode Exit fullscreen mode

Promises

  • Promises represent a value that may be available now, in the future, or never. A promise can be in one of three states: pending, fulfilled, or rejected. This improves readability compared to callbacks.
const fetchData = new Promise((resolve, reject) => {
  setTimeout(() => resolve("Data fetched!"), 1000);
});

fetchData.then(result => console.log(result)).catch(err => console.log(err));
Enter fullscreen mode Exit fullscreen mode

Async/Await

  • This is built on top of promises and allows you to write asynchronous code that looks synchronous, making it easier to understand and maintain. It uses the async keyword for a function and await for the promise's resolution.
async function fetchData() {
  const result = await new Promise((resolve) => {
    setTimeout(() => resolve("Data fetched!"), 1000);
  });
  console.log(result);
}

fetchData();
Enter fullscreen mode Exit fullscreen mode

Event Loop

  • The event loop is responsible for managing the execution of asynchronous code. When an asynchronous task is initiated (e.g., a timeout, an API request), the task is offloaded to the browser or Node.js, and once it completes, the callback or promise is pushed to the callback queue to be executed when the main thread (call stack) is free.
  • Understanding these concepts helps handle I/O operations efficiently and makes web applications more responsive.

Callbacks

  • The callback pattern in JavaScript is a technique where a function (callback) is passed as an argument to another function. The receiving function then executes the callback after completing its task, allowing you to handle asynchronous behavior, like handling events, API calls, or file reading, without blocking the main thread.

How Callbacks Work

  • In JavaScript, when you pass a function as an argument, it can be executed at some point within the outer function. The callback pattern is especially useful for handling code that needs to run after some operation has finished, like waiting for an API request or a timer.
function doSomething(callback) {
  console.log("Doing something...");
  callback(); // Invoking the callback function
}

function myCallback() {
  console.log("Callback executed!");
}

doSomething(myCallback);
Enter fullscreen mode Exit fullscreen mode

Callback Hell

  • One of the challenges with callbacks is that they can easily lead to deeply nested structures, especially when you have multiple asynchronous operations depending on each other. This is often referred to as "callback hell" and can make code difficult to read and maintain.
setTimeout(() => {
  console.log("Step 1 complete");
  setTimeout(() => {
    console.log("Step 2 complete");
    setTimeout(() => {
      console.log("Step 3 complete");
    }, 1000);
  }, 1000);
}, 1000);
Enter fullscreen mode Exit fullscreen mode
  • To avoid this complexity, modern JavaScript uses Promises and async/await, which make code more readable and maintainable.

Error Handling in Callbacks

  • In the callback pattern, errors are typically handled by passing them as the first argument to the callback function. If the first argument is null or undefined, it indicates no error; otherwise, it means an error has occurred.
function fetchData(callback) {
  setTimeout(() => {
    const error = false;
    if (error) {
      callback("Error occurred", null);
    } else {
      callback(null, "Fetched Data");
    }
  }, 2000);
}

function handleData(error, data) {
  if (error) {
    console.log("Error: " + error);
  } else {
    console.log("Data: " + data);
  }
}

fetchData(handleData);
Enter fullscreen mode Exit fullscreen mode

Summary

  • Asynchronous programming in JavaScript allows tasks to run without blocking the main thread, enabling efficient handling of operations like API requests, file I/O, or timers.
  • A callback is a function passed to another function to be executed later, often after an asynchronous operation completes.
  • Synchronous callbacks run immediately, while asynchronous callbacks are executed once the operation (like fetching data) finishes.
  • Synchronous callbacks are the functions which are used as callback on map, filter, forEach etc.

Commonly asked interview questions

Asynchronous Programming

  • What is asynchronous programming, and how does it work in JavaScript?
  • What is the event loop, and how does it handle asynchronous code in JavaScript?
  • What is the difference between synchronous and asynchronous code in JavaScript?
  • What are Promises, and how do they improve asynchronous code?
  • How does JavaScript handle asynchronous errors, and what are the common ways to handle them?
  • What are some use cases for asynchronous programming?

Callback

  • What is a callback in JavaScript, and how is it used?
  • What are the advantages and disadvantages of using callbacks in JavaScript?
  • What is callback hell, and how can you avoid it?
  • What is the difference between a synchronous callback and an asynchronous callback?
  • How does the forEach method in arrays use callbacks?

Top comments (0)