Callback Functions

  • This lesson explains how callback functions work in JavaScript.
  • Introduction to Callback Functions

    JavaScript is a single-threaded language, but it can still handle time-consuming tasks such as:

    • Fetching data from a server

    • Reading files

    • Timers and delays

    • Event handling

    To manage such tasks without blocking the main thread, JavaScript uses callbacks.

    In this lesson, we will understand:

    1. What callbacks are

    2. Why callbacks are needed

    3. Callback hell and its problems

    Callbacks

    What Is a Callback Function ?

    A callback function is a function that is passed as an argument to another function and is executed later, after a task is completed.

    Simple Definition

    A callback is a function that runs after another function finishes its work.

    Why Are Callbacks Needed ?

    Some operations take time:

    • API requests

    • File loading

    • Timers

    • Database queries

    If JavaScript waited synchronously:

    • UI would freeze

    • Page would stop responding

    Callbacks allow JavaScript to:

    • Start a task

    • Continue other work

    • Execute callback when task finishes

JavaScript Callback Function Example

This code demonstrates the use of a callback function where sayBye is executed after the greet function completes.

function greet(name, callback) {
  console.log("Hello " + name);
  callback();
}

function sayBye() {
  console.log("Goodbye");
}

greet("Rahul", sayBye);

  • How This Works

    1. greet() is called

    2. sayBye is passed as a callback

    3. callback() executes after greeting

JavaScript Asynchronous Callback Handling

This code shows how a callback is used to process data after an asynchronous operation like setTimeout completes.

function fetchData(callback) {
  setTimeout(() => {
    console.log("Data fetched");
    callback();
  }, 2000);
}

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

fetchData(processData);
  • Real-Life Analogy

    You order food at a restaurant:

    • You place an order

    • You do other things

    • Restaurant calls you when food is ready

    That “call” is a callback.

JavaScript setTimeout Basic Example

This code demonstrates how setTimeout is used to execute a function after a specified delay.

setTimeout
setTimeout(function () {
  console.log("Executed after 2 seconds");
}, 2000);

JavaScript Event Listener Example

This code demonstrates how addEventListener is used to execute a function when a button is clicked.

Event Listeners
button.addEventListener("click", function () {
  console.log("Button clicked");
});
  • The function runs only after the click event occurs.

    Advantages of Callbacks

    • Enable asynchronous programming

    • Keep application responsive

    • Simple concept

    • Widely supported

    Disadvantages of Callbacks

    • Hard to read when nested

    • Difficult to debug

    • Error handling becomes complex

    This leads to the next topic.

    Callback Hell

    What Is Callback Hell ?

    Callback Hell occurs when callbacks are nested inside callbacks, creating deeply indented and unreadable code.

    It is also known as:

    • Pyramid of Doom

    • Callback Pyramid

JavaScript Callback Hell (Nested setTimeout)

This code demonstrates callback hell using nested setTimeout functions to execute steps sequentially with delays.

setTimeout(() => {
  console.log("Step 1");

  setTimeout(() => {
    console.log("Step 2");

    setTimeout(() => {
      console.log("Step 3");

      setTimeout(() => {
        console.log("Step 4");
      }, 1000);

    }, 1000);

  }, 1000);

}, 1000);
  • Problems with Callback Hell

    • Poor readability

    • Hard to maintain

    • Difficult error handling

    • Complex debugging

    • Not scalable

  • Problems with Callback Hell

    • Poor readability

    • Hard to maintain

    • Difficult error handling

    • Complex debugging

    • Not scalable

    Visual Structure of Callback Hell

    function() {

      function() {

        function() {

          function() {

            function() {

            }

          }

        }

      }

    }

    This structure is difficult to understand and modify.

    Real-World Example (Login Flow)

    login(user, () => {

      getProfile(() => {

        getOrders(() => {

          processPayment(() => {

            console.log("Done");

          });

        });

      });

    });

    Each step depends on the previous one, creating deep nesting.

    Why Callback Hell Is Dangerous

    • Small change breaks logic

    • Error handling must be repeated

    • Code becomes fragile

    How Developers Avoid Callback Hell

    Although callbacks are important, modern JavaScript prefers:

    • Named functions

    • Modular code

    • Promises

    • async/await

    (These will be covered in upcoming lessons.)

JavaScript Multiple setTimeout Execution Order

This code demonstrates how multiple setTimeout functions run independently based on their delays.

function step1() {
  console.log("Step 1");
}

function step2() {
  console.log("Step 2");
}

setTimeout(step1, 1000);
setTimeout(step2, 2000);
  • Best Practices When Using Callbacks

    • Keep callbacks small

    • Avoid deep nesting

    • Use meaningful function names

    • Handle errors properly

    • Prefer modern async patterns

    Common Mistakes

    • Calling callback immediately instead of passing it

    • Forgetting error handling

    • Creating deeply nested callbacks

    • Mixing sync and async logic