Node.js6 min read
Understanding Callbacks in Node.js
Master callback patterns in Node.js. Understand error-first callbacks and avoid callback hell.
Sarah Chen
December 19, 2025
0.0k0
Understanding Callbacks in Node.js
Callbacks are functions passed as arguments. Node.js uses them everywhere.
What's a Callback?
function greet(name, callback) {
const message = `Hello, ${name}!`;
callback(message);
}
greet('Alice', (msg) => {
console.log(msg); // Hello, Alice!
});
Why Callbacks?
Node.js is non-blocking. Instead of waiting:
// Blocking (bad in Node.js)
const data = readFileSync('file.txt'); // Waits here
console.log(data);
// Non-blocking (good)
readFile('file.txt', (err, data) => {
console.log(data); // Runs when file is read
});
console.log('This runs immediately!');
Error-First Callbacks
Node.js convention: first argument is always error.
const fs = require('fs');
fs.readFile('file.txt', 'utf8', (err, data) => {
if (err) {
console.error('Error:', err.message);
return;
}
console.log('Data:', data);
});
Creating Error-First Callbacks
function divide(a, b, callback) {
if (b === 0) {
callback(new Error('Cannot divide by zero'));
return;
}
callback(null, a / b);
}
divide(10, 2, (err, result) => {
if (err) {
console.error(err.message);
return;
}
console.log('Result:', result); // 5
});
Callback Hell (The Problem)
// Nested callbacks = hard to read
fs.readFile('file1.txt', (err, data1) => {
if (err) return handleError(err);
fs.readFile('file2.txt', (err, data2) => {
if (err) return handleError(err);
fs.readFile('file3.txt', (err, data3) => {
if (err) return handleError(err);
// Finally do something with data1, data2, data3
console.log(data1, data2, data3);
});
});
});
Avoiding Callback Hell
1. Named functions:
function handleFile1(err, data1) {
if (err) return handleError(err);
fs.readFile('file2.txt', handleFile2);
}
function handleFile2(err, data2) {
if (err) return handleError(err);
console.log('Done!');
}
fs.readFile('file1.txt', handleFile1);
2. Use Promises (better):
const fs = require('fs').promises;
async function readFiles() {
const data1 = await fs.readFile('file1.txt');
const data2 = await fs.readFile('file2.txt');
const data3 = await fs.readFile('file3.txt');
return [data1, data2, data3];
}
Convert Callback to Promise
const { promisify } = require('util');
// Old callback style
const readFile = promisify(fs.readFile);
// Now use with async/await
const data = await readFile('file.txt', 'utf8');
Key Takeaway
Callbacks are foundational in Node.js. Always handle errors first. Avoid deep nesting with named functions or better yet, use Promises and async/await for cleaner code.
#Node.js#Callbacks#Async#Beginner