A callback function is a function that is passed as an argument to another function and is executed after some operation or event is completed. Callback functions are commonly used in programming to handle asynchronous operations, manage events, or implement custom behaviors.

Key Characteristics:

  1. Passed as an Argument: The callback function is provided as an argument to another function.
  2. Executed Later: It is invoked either:
    • Immediately within the function it was passed to.
    • After a specific condition is met (e.g., an event occurs or a task completes).
  3. Customizable: It allows dynamic behavior by enabling you to define what happens after an operation.

Common Use Cases:

Functional Programming: Allows reusability and customization of behaviors in higher-order functions.

// Example: Array map function
const numbers = [1, 2, 3];
const doubled = numbers.map(function callback(num) {
    return num * 2;
});
console.log(doubled); // Output: [2, 4, 6]

Event Handling: Used in event-driven systems to execute code when an event occurs.

document.addEventListener('click', function callback(event) {
    console.log('Element clicked!', event);
});

Asynchronous Operations: Often used in asynchronous programming to handle tasks like file reading, API calls, or timers.

// Example in JavaScript
setTimeout(function callback() {
    console.log("This runs after 2 seconds");
}, 2000);

Synchronous vs Asynchronous Callback:

Asynchronous Callback: Executes later, typically when the operation completes.

function fetchData(callback) {
    setTimeout(() => {
        callback("Data fetched");
    }, 1000);
}
fetchData(function callback(data) {
    console.log(data);
});
// Output (after 1 second): Data fetched

Synchronous Callback: Executes immediately within the containing function.

function greet(name, callback) {
    callback(name);
}
greet("Alice", function callback(name) {
    console.log(`Hello, ${name}!`);
});
// Output: Hello, Alice!

Benefits:

  • Flexibility in defining post-operation behavior.
  • Decouples logic, making code reusable and modular.
  • Simplifies asynchronous operations when properly used.

Drawbacks:

  • Can lead to callback hell (nested callbacks) if not handled properly.
  • Makes debugging harder in some scenarios.
💡
To mitigate issues, modern programming often uses promises or async/await (e.g., in JavaScript).

Bonus Contents:


Example 1: Ordering Food at a Restaurant

When you order food, you tell the waiter (function) what you'd like to eat (parameters). Once the food is ready, the waiter will call you (callback) to let you know.

function orderFood(order, callback) {
    console.log(`Order placed: ${order}`);
    setTimeout(() => {
        callback(order);
    }, 3000); // Food takes 3 seconds to prepare
}

orderFood("Pizza", function serveFood(order) {
    console.log(`Your ${order} is ready!`);
});

Explanation:

  • orderFood: Takes your order and prepares it.
  • Callback Function: Called once the food is ready (after 3 seconds).

Example 2: Alarm Clock

You set an alarm (a function), and when the time comes, the alarm rings (callback).

function setAlarm(time, callback) {
    console.log(`Alarm set for ${time}`);
    setTimeout(() => {
        callback();
    }, 2000); // Simulating the time to ring
}

setAlarm("7:00 AM", function ringAlarm() {
    console.log("Wake up! Your alarm is ringing!");
});

Explanation:

  • You pass the ringAlarm function as a callback.
  • Once the simulated 2 seconds are up, the alarm rings.

Example 3: Phone Call Callback

You call a friend (function) and leave a message. When they’re free, they call you back (callback function).

function callFriend(message, callback) {
    console.log(`You: "${message}"`);
    setTimeout(() => {
        callback("Got your message! Let's catch up soon.");
    }, 2000); // Simulating delay before they respond
}

callFriend("Hey! Call me when you’re free.", function callback(reply) {
    console.log(`Friend: "${reply}"`);
});

Explanation:

  • You initiate the call by sending a message.
  • Your friend responds later using the callback function.

Example 4: Cooking with Steps

You’re baking a cake. After you mix the ingredients, you need to wait for the oven to preheat before baking the cake.

function preheatOven(callback) {
    console.log("Preheating the oven...");
    setTimeout(() => {
        console.log("Oven is ready!");
        callback(); // Call the next step
    }, 2000);
}

function bakeCake() {
    console.log("Cake is now baking...");
}

preheatOven(bakeCake);

Explanation:

  • The oven needs to be ready before the cake can bake.
  • You use a callback function (bakeCake) to ensure the baking starts only after the oven is preheated.

Example 5: Doing Laundry

When you load the washing machine, you want it to notify you when it’s done so you can hang the clothes.

function startWashingMachine(callback) {
    console.log("Washing machine started...");
    setTimeout(() => {
        console.log("Washing done!");
        callback();
    }, 3000); // Simulating washing time
}

function hangClothes() {
    console.log("Clothes are now hung to dry.");
}

startWashingMachine(hangClothes);

Explanation:

  • The machine (function) does the washing.
  • It calls you back to hang the clothes when it’s done.

Why Callbacks?
Callbacks are a way to handle actions that take time or depend on other actions, ensuring you don't proceed until they’re complete. They're like a signal saying, "Hey, I’m done. Now it’s your turn to act!"