Understanding Callbacks in JavaScript

Hakim Ali
2 min readMar 18, 2023

Callbacks are a fundamental concept in JavaScript that is often used to handle asynchronous operations. They allow us to pass functions as arguments to other functions and execute them when a particular task is completed.

In this article, we will explore the basics of callbacks in JavaScript and progress to more advanced techniques.

Basic Concept: Passing Functions as Arguments In JavaScript, functions are first-class citizens, which means they can be treated like any other variable. This feature allows us to pass functions as arguments to other functions.

Here’s an example:

function add(a, b, callback) {
const result = a + b;
callback(result);
}

function printResult(result) {
console.log(`The result is ${result}`);
}
add(5, 10, printResult); // Output: The result is 15

In this example, we defined a function called add that takes two numbers a and b and a callback function as arguments. Inside the add function, we added the two numbers and stored the result in a variable called result. We then passed this result to the callback function.

We also defined a second function called printResult, which takes a single argument result and logs it to the console.

Finally, we called the add function with values of 5 and 10 and passed the printResult function as a callback. The add function executed and passed the result to the printResult function, which logged it to the console.

Intermediate Concept: Nesting Callbacks In JavaScript, we can also nest callbacks inside other callbacks to handle more complex asynchronous operations.

Here’s an example:

function getUser(userId, callback) {
setTimeout(() => {
const user = { id: userId, name: 'John Doe' };
callback(user);
}, 1000);
}

function getUserPosts(user, callback) {
setTimeout(() => {
const posts = [
{ id: 1, title: 'Post 1' },
{ id: 2, title: 'Post 2' },
{ id: 3, title: 'Post 3' },
];
callback(user, posts);
}, 1000);
}
function getPostComments(post, callback) {
setTimeout(() => {
const comments = [
{ id: 1, text: 'Comment 1' },
{ id: 2, text: 'Comment 2' },
];
callback(post, comments);
}, 1000);
}
getUser(1, (user) => {
getUserPosts(user, (user, posts) => {
posts.forEach((post) => {
getPostComments(post, (post, comments) => {
console.log(`Post ${post.id}: ${post.title}`);
comments.forEach((comment) => {
console.log(` Comment ${comment.id}: ${comment.text}`);
});
});
});
});
});

In this example, we defined three functions that simulate asynchronous operations using setTimeout. The getUser function takes a user ID and a callback function as arguments and returns the user object after a delay of 1 second.

The getUserPosts function takes a user object and a callback function as arguments and returns an array of posts for that user after a delay of 1 second.

The getPostComments function takes a post object and a callback function as arguments and returns an array of comments for that post after a delay of 1 second.

We then nested these functions inside each other to simulate a more complex asynchronous operation. The getUser function calls the getUserPosts function, which calls the getPostComments function for each post.

Advanced Concept: Promises

--

--

Hakim Ali

A full stack engineer with 10 years of programming experience in JavaScript, vue.js, react.js and .NET technologies