Node.js Callbacks Practice Questions with Solutions

Introduction

Callbacks are one of the fundamental concepts in Node.js. A callback is a function passed to another function so it can be executed later, often after an asynchronous operation finishes. In this chapter, you will practice simple callbacks, callback parameters, asynchronous callbacks, file operations, error-first callbacks, nested callbacks, and practical Node.js examples. The examples gradually move from beginner level to real-world callback handling. Node.js Callbacks Practice Questions with Solutions help to understand the concepts.

Question 1: How do you create a simple callback function?

Problem

Create a function that accepts another function as a callback and executes it after displaying a message.

Solution

function greet(name, callback) {

    console.log("Hello " + name);

    callback();
}

function showMessage() {

    console.log("Welcome to Node.js!");
}

greet("Rahul", showMessage);

Output

Hello Rahul
Welcome to Node.js!

Step-by-Step Explanation

The greet() function accepts two parameters:

function greet(name, callback)

The second parameter is a callback function.

Inside greet():

callback();

executes the callback.

We then pass showMessage as the callback:

greet("Rahul", showMessage);

Question 2: How do you pass data to a callback?

Problem

Create a function that calculates the square of a number and sends the result to a callback.

Solution

function calculateSquare(number, callback) {

    const result = number * number;

    callback(result);
}

function displayResult(result) {

    console.log("Square:", result);
}

calculateSquare(6, displayResult);

Output

Square: 36

Step-by-Step Explanation

The calculateSquare() function receives:

number
callback

It calculates:

const result = number * number;

Then sends the result to the callback:

callback(result);

The callback receives the value:

function displayResult(result)

Important Point

Callbacks can receive data through function arguments.


Question 3: How do callbacks work with asynchronous code?

Problem

Create an asynchronous function that displays a message after two seconds and then executes a callback.

Solution

function downloadFile(callback) {

    console.log("Downloading file...");

    setTimeout(() => {

        console.log("File downloaded.");

        callback();

    }, 2000);
}

function downloadComplete() {

    console.log("Download completed successfully!");
}

downloadFile(downloadComplete);

Output

Immediately:

Downloading file...

After approximately 2 seconds:

File downloaded.
Download completed successfully!

Step-by-Step Explanation

setTimeout() schedules code to run later:

setTimeout(() => {
    // Code
}, 2000);

After the timeout finishes, the callback is executed:

callback();

This is an example of an asynchronous callback.


Question 4: How do you use a callback to perform addition?

Problem

Create a function that accepts two numbers and uses a callback to return their sum.

Solution

function addNumbers(a, b, callback) {

    const sum = a + b;

    callback(sum);
}

function showSum(result) {

    console.log("Sum:", result);
}

addNumbers(20, 30, showSum);

Output

Sum: 50

Step-by-Step Explanation

The function receives:

a
b
callback

It calculates:

const sum = a + b;

Then passes the result to the callback:

callback(sum);

The callback receives 50 and displays it.

Try It Yourself

Change:

addNumbers(20, 30, showSum);

to:

addNumbers(100, 250, showSum);

Output:

Sum: 350

Question 5: How do you use the error-first callback pattern?

Problem

Create a function that checks a number and returns either an error or a successful result through a callback.

Solution

function checkNumber(number, callback) {

    if (number < 0) {

        callback(
            new Error("Number cannot be negative."),
            null
        );

        return;
    }

    callback(null, number);
}

checkNumber(10, (error, result) => {

    if (error) {

        console.log("Error:", error.message);

        return;
    }

    console.log("Number:", result);
});

Output

Number: 10

Step-by-Step Explanation

Node.js commonly uses an error-first callback pattern.

The callback receives:

(error, result)

When an error occurs:

callback(error, null);

When the operation succeeds:

callback(null, result);

The caller checks the error first:

if (error) {
    // Handle error
}

Question 6: How do you use callbacks with the Node.js File System module?

Problem

Create a file and then read it using asynchronous callbacks.

Solution

const fs = require("fs");

fs.writeFile(
    "message.txt",
    "Hello from Node.js!",
    (error) => {

        if (error) {

            console.log("Error writing file:", error.message);

            return;
        }

        console.log("File created successfully.");

        fs.readFile(
            "message.txt",
            "utf8",
            (error, data) => {

                if (error) {

                    console.log(
                        "Error reading file:",
                        error.message
                    );

                    return;
                }

                console.log("File content:", data);
            }
        );
    }
);

Output

File created successfully.
File content: Hello from Node.js!

Step-by-Step Explanation

First, writeFile() creates the file:

fs.writeFile(...)

Its callback runs after the operation finishes.

After the file is successfully created, readFile() is called:

fs.readFile(...)

Its callback receives:

(error, data)

The data contains the file content.

Question 7: How do you execute multiple callbacks in sequence?

Problem

Create three functions that run one after another using callbacks.

Solution

function firstTask(callback) {

    console.log("First task completed.");

    callback();
}

function secondTask(callback) {

    console.log("Second task completed.");

    callback();
}

function thirdTask() {

    console.log("Third task completed.");
}

firstTask(() => {

    secondTask(() => {

        thirdTask();

    });

});

Output

First task completed.
Second task completed.
Third task completed.

Step-by-Step Explanation

The first function receives a callback:

firstTask(() => {
    ...
});

After completing its work, it calls the callback.

The callback starts the second task:

secondTask(() => {
    ...
});

After the second task finishes, the third task starts.


Question 8: What is callback hell?

Problem

Understand a situation where multiple nested callbacks make code difficult to read.

Solution

Consider:

function login(username, callback) {

    console.log("User logged in.");

    callback();
}

function getProfile(callback) {

    console.log("Profile loaded.");

    callback();
}

function getCourses(callback) {

    console.log("Courses loaded.");

    callback();
}

function showDashboard() {

    console.log("Dashboard displayed.");
}

login("Rahul", () => {

    getProfile(() => {

        getCourses(() => {

            showDashboard();

        });

    });

});

Output

User logged in.
Profile loaded.
Courses loaded.
Dashboard displayed.

Step-by-Step Explanation

The callbacks are nested:

login()
   └── getProfile()
          └── getCourses()
                 └── showDashboard()

With many asynchronous operations, this pattern can become deeply nested and difficult to maintain.

This situation is commonly called callback hell or the pyramid of doom.


Question 9: How do you create a reusable callback-based function?

Problem

Create a reusable function that performs an operation and allows different callbacks to handle the result.

Solution

function calculate(a, b, operation, callback) {

    let result;

    if (operation === "add") {

        result = a + b;

    } else if (operation === "subtract") {

        result = a - b;

    } else {

        callback(
            new Error("Unknown operation."),
            null
        );

        return;
    }

    callback(null, result);
}

calculate(20, 10, "add", (error, result) => {

    if (error) {

        console.log("Error:", error.message);

        return;
    }

    console.log("Result:", result);
});

Output

Result: 30

Step-by-Step Explanation

The function accepts four parameters:

calculate(
    a,
    b,
    operation,
    callback
)

It checks the requested operation.

For addition:

result = a + b;

For subtraction:

result = a - b;

Then the callback receives:

callback(null, result);

Question 10: How do you build a practical callback-based Node.js application?

Problem

Create a small Node.js program that:

  • Reads student data from a file.
  • Parses JSON.
  • Handles file errors.
  • Handles invalid JSON.
  • Sends the final student data to a callback.

Solution

First create students.json:

[
    {
        "id": 1,
        "name": "Rahul",
        "course": "Node.js"
    },
    {
        "id": 2,
        "name": "Priya",
        "course": "JavaScript"
    }
]

Now create index.js:

const fs = require("fs");

function getStudents(callback) {

    fs.readFile(
        "students.json",
        "utf8",
        (error, data) => {

            if (error) {

                callback(
                    new Error("Unable to read students file."),
                    null
                );

                return;
            }

            let students;

            try {

                students = JSON.parse(data);

            } catch (error) {

                callback(
                    new Error("Invalid student JSON data."),
                    null
                );

                return;
            }

            callback(null, students);
        }
    );
}

getStudents((error, students) => {

    if (error) {

        console.log("Error:", error.message);

        return;
    }

    console.log("Students:");

    students.forEach((student) => {

        console.log(
            `${student.id}. ${student.name} - ${student.course}`
        );
    });
});

Output

Students:
1. Rahul - Node.js
2. Priya - JavaScript

Step-by-Step Explanation

Step 1: Import File System

const fs = require("fs");

The fs module provides file system functionality.

Step 2: Create a reusable function

function getStudents(callback)

The function accepts a callback to return the final result.

Step 3: Read the JSON file

fs.readFile(
    "students.json",
    "utf8",
    (error, data) => {

The operation is asynchronous.

Step 4: Check for file errors

if (error) {
    callback(
        new Error("Unable to read students file."),
        null
    );

    return;
}

If the file cannot be read, the callback receives an error.

Step 5: Parse JSON

students = JSON.parse(data);

Because JSON parsing can throw an exception, it is placed inside try...catch.

Step 6: Return the data

callback(null, students);

The first argument is null because there is no error.

Step 7: Handle the result

getStudents((error, students) => {

The caller checks the error:

if (error) {
    console.log(error.message);
    return;
}

If everything succeeds, the student data is displayed.

Key Takeaways

  • A callback is a function passed to another function.
  • The receiving function can execute the callback when its work is complete.
  • Callbacks can receive data through parameters.
  • Node.js uses callbacks extensively for asynchronous operations.
  • setTimeout() is a simple way to understand asynchronous callbacks.
  • Node.js traditionally uses the error-first callback pattern.
  • The error-first pattern commonly looks like:
callback(error, result);
  • Successful operations commonly use:
callback(null, result);
  • Errors should be checked before processing callback results.
  • The Node.js fs module provides many callback-based asynchronous methods.
  • Callbacks can be used to control the order of asynchronous operations.
  • Too many nested callbacks can create callback hell.
  • Promises and async/await provide alternative ways to manage complex asynchronous operations.
  • Callbacks are still important because many Node.js APIs and libraries use them.
  • A good callback-based function should clearly define what arguments its callback receives.
  • Error handling should be included in asynchronous callback code.
  • Reusable callback functions can make Node.js code more flexible.
  • Understanding callbacks makes it easier to understand Promises and async/await.

FAQs

1. What is a callback in Node.js?

A callback is a function passed as an argument to another function so that it can be executed later.

Example:

function greet(name, callback) {

    console.log("Hello " + name);

    callback();
}

Here, callback is a function parameter.

2. Why are callbacks important in Node.js?

Callbacks are important because Node.js performs many operations asynchronously.

For example, file reading can continue without blocking the rest of the application:

fs.readFile("file.txt", "utf8", (error, data) => {
    // Handle result
});

The callback runs after the file operation finishes.

3. What is an error-first callback?

An error-first callback is a common Node.js convention where the first callback argument represents an error.

Example:

callback(error, data);

When the operation succeeds:

callback(null, data);

The caller normally checks the error first.

4. What is callback hell in Node.js?

Callback hell occurs when many callbacks become deeply nested, making code difficult to read and maintain.

Example:

first()
   └── second()
          └── third()
                 └── fourth()

Promises and async/await can make complex asynchronous flows easier to manage.

5. Are callbacks asynchronous in Node.js?

Not always.

A callback is simply a function passed to another function. Whether it runs synchronously or asynchronously depends on the function that receives it.

For example, this callback runs synchronously:

function test(callback) {

    callback();
}

test(() => {
    console.log("Hello");
});

But a callback passed to an asynchronous API such as fs.readFile() runs after the asynchronous operation completes.

6. How do you handle errors in a callback?

Use the error-first pattern and check the error before using the result.

Example:

someFunction((error, result) => {

    if (error) {

        console.log(error.message);

        return;
    }

    console.log(result);
});

This prevents the application from processing an invalid or missing result.

7. What is the difference between callbacks and Promises?

Callbacks pass a function to another function to handle the result.

Promises represent the eventual completion or failure of an asynchronous operation and can be handled using .then() and .catch().

Callback example:

getData((error, data) => {
    // Handle result
});

Promise example:

getData()
    .then((data) => {
        // Handle result
    })
    .catch((error) => {
        // Handle error
    });

Both approaches are important to understand when learning asynchronous Node.js programming.

Written by Shubhranshu Shekhar, who has trained 20000+ students in coding.

Scroll to Top