Callbacks are one of the most important concepts in JavaScript, especially when working with asynchronous operations.
A callback is simply a function passed into another function as an argument. The callback function is executed later after a task is completed.
Callbacks are commonly used in:
- Timers
- API requests
- Event handling
- Animations
- Asynchronous operations
Understanding callbacks is essential before learning promises and async/await.
Why Callbacks Exist
JavaScript is single-threaded, meaning it executes one task at a time. Some operations, such as API requests or timers, take time to complete.
Instead of freezing the application while waiting, JavaScript continues running other code and executes a callback later when the operation finishes.
This behavior helps create responsive and interactive applications.
Basic Callback Example
In this example, a function is passed as an argument to another function.
const greetUser = (name, callback) => {
console.log(`Hello ${name}`);
callback();
};
const showMessage = () => {
console.log("Welcome to IgKnight");
};
greetUser("Alex", showMessage);
The
showMessage
function becomes the callback.
How Callbacks Work
A callback function is not executed immediately. Instead, it is passed into another function and executed later when needed.
This allows JavaScript to control when certain logic should run.
Callbacks with setTimeout()
One of the most common callback examples uses
setTimeout().
The callback runs after a delay.
console.log("Start");
setTimeout(() => {
console.log("Executed after 2 seconds");
}, 2000);
console.log("End");
Even though the timeout appears in the middle, JavaScript continues executing other code first.
Callbacks in Array Methods
Array methods heavily rely on callback functions.
Methods like
map(),
filter(),
and
forEach()
all use callbacks internally.
const numbers = [1, 2, 3];
numbers.forEach(number => {
console.log(number);
});
The function passed into
forEach()
is a callback.
Real-World Example
Callbacks are commonly used in event handling.
const button =
document.querySelector("button");
button.addEventListener("click", () => {
console.log("Button clicked");
});
The function passed to
addEventListener()
executes only when the user clicks the button.
Asynchronous Callbacks
Many asynchronous JavaScript operations use callbacks.
For example:
- Timers
- API requests
- File operations
- Database queries
The callback runs after the asynchronous task completes.
Callback Hell
Excessive nested callbacks can make code difficult to read and maintain. This problem is commonly called callback hell.
getUser(userId, (user) => {
getOrders(user.id, (orders) => {
getPaymentDetails(orders, (payment) => {
console.log(payment);
});
});
});
Deep nesting quickly becomes difficult to manage.
Promises and async/await were introduced to solve this problem.
Synchronous vs Asynchronous Callbacks
| Type | Behavior |
|---|---|
| Synchronous Callback | Executes immediately |
| Asynchronous Callback | Executes later after a task completes |
Why Callbacks Are Important
Even though modern JavaScript often uses promises and async/await, callbacks are still fundamental to understanding how JavaScript works internally.
Many APIs, libraries, and browser features still rely on callback patterns.
Common Beginner Mistakes
- Calling the callback immediately instead of passing it
- Forgetting that asynchronous callbacks execute later
- Creating deeply nested callback structures
- Confusing synchronous and asynchronous execution order
Best Practices
- Keep callback functions small and focused
- Avoid deeply nested callbacks
- Use descriptive callback names
- Use promises or async/await for complex async flows
Summary
Callbacks are functions passed into other functions and executed later. They are a core part of asynchronous JavaScript programming and are widely used in timers, events, and API operations.
Understanding callbacks is essential for learning promises, async/await, and advanced asynchronous JavaScript concepts.