JavaScript Callbacks Interview Questions & Answers

4 interview angles 3 min read source

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?

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

  1. What is a callback function?
    • A function passed as an argument to another function, to be executed later.
  2. 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).
  3. 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.
  4. 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) { ... }).
  5. How do callbacks compare to Promises and async/await?
    • Promises and async/await provide better readability, error handling, and composability.
  6. Give an example of using a callback in an array method.
    • arr.map(function(x) { return x * 2; })
  7. 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/await into 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 no throw across 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.promisify in Node, or wrap in new Promise. Most core Node APIs also ship promise variants under fs/promises and similar.