JavaScript Callbacks Interview Questions & Answers
Callbacks are a fundamental concept in JavaScript for handling asynchronous operations and event-driven programming. Understanding callbacks is essential for mastering JavaScript’s async patterns and for interview success.
Table of Contents
- What is a Callback?
- Synchronous vs Asynchronous Callbacks
- Callback Examples
- Callback Hell
- Callback vs Promise vs Async/Await
- Interview Questions
What is a Callback?
A callback is a function passed as an argument to another function, to be executed later (either synchronously or asynchronously).
Example:
function greet(name, callback) {
console.log('Hello, ' + name + '!');
callback();
}
greet('Alice', function() {
console.log('Greeting complete.');
});
// Output:
// Hello, Alice!
// Greeting complete.
Synchronous vs Asynchronous Callbacks
- Synchronous callback: Executed immediately during the execution of the containing function.
- Asynchronous callback: Executed after the containing function has finished, often in response to an event or after a delay.
Synchronous Example:
[1, 2, 3].forEach(function(item) {
console.log(item);
});
// Output: 1 2 3
Asynchronous Example:
setTimeout(function() {
console.log('Executed after 1 second');
}, 1000);
Callback Examples
1. Event Handling:
document.getElementById('btn').addEventListener('click', function() {
alert('Button clicked!');
});
2. Array Methods:
const numbers = [1, 2, 3];
const doubled = numbers.map(function(num) {
return num * 2;
});
console.log(doubled); // [2, 4, 6]
3. Custom Async Function:
function fetchData(callback) {
setTimeout(function() {
callback('Data loaded');
}, 1000);
}
fetchData(function(result) {
console.log(result); // 'Data loaded'
});
Callback Hell
- Callback hell (also known as “Pyramid of Doom”) occurs when callbacks are nested within other callbacks, making code hard to read and maintain.
Example:
login(user, function(err, userData) {
if (err) return handleError(err);
getProfile(userData, function(err, profile) {
if (err) return handleError(err);
getPosts(profile, function(err, posts) {
if (err) return handleError(err);
// ... more nested callbacks
});
});
});
- Solutions: Use Promises or async/await to flatten the code structure.
Callback vs Promise vs Async/Await
| Feature | Callback | Promise | Async/Await |
|---|---|---|---|
| Syntax | Function arg | .then/.catch | async/await |
| Error Handling | Callback param | .catch | try/catch |
| Readability | Can be nested | Flat chaining | Synchronous style |
| Composability | Hard | Easy | Easiest |
| Return Value | None | Promise | Promise |
Interview Questions
- What is a callback function?
- A function passed as an argument to another function, to be executed later.
- What is the difference between synchronous and asynchronous callbacks?
- Synchronous callbacks run immediately; asynchronous run after the current function completes (e.g., after a delay or event).
- What is callback hell and how can you avoid it?
- Deeply nested callbacks that make code hard to read; avoid with Promises or async/await.
- How do you handle errors in callback-based async code?
- By convention, the first argument of the callback is an error object (Node.js style:
function(err, result) { ... }).
- By convention, the first argument of the callback is an error object (Node.js style:
- How do callbacks compare to Promises and async/await?
- Promises and async/await provide better readability, error handling, and composability.
- Give an example of using a callback in an array method.
arr.map(function(x) { return x * 2; })
- How do you convert a callback-based function to a Promise-based one?
- Wrap the callback in a Promise constructor.
Additional Resources
Understanding callbacks is the foundation for mastering asynchronous JavaScript. Practice writing and refactoring callback-based code for interviews!
Interview angle
- “What is callback hell, and what actually fixes it?” - deep nesting from sequential async steps. Promises flatten it into a chain and
async/awaitinto straight-line code. Naming the callbacks helps readability but not the error handling, which is the real problem. - “What is the Node error-first convention?” -
(err, result) => ..., error checked first. It exists because there is nothrowacross an async boundary; a thrown error inside a callback escapes to the top level rather than to the caller. - “What is inversion of control here?” - you hand your continuation to someone else’s code and trust it to call it once, at the right time, with the right arguments. A library calling it twice, or never, is untestable from your side - which is the argument promises settle by being single-settlement.
- “How do you convert callbacks to promises?” -
util.promisifyin Node, or wrap innew Promise. Most core Node APIs also ship promise variants underfs/promisesand similar.