Callback Functions
What is a Callback Function?
A callback is a function passed as an argument to another function, which is then invoked inside the outer function to complete some kind of action or routine.
Try Callback Functions
Code Editor
Console Output
Click "Run" to execute your code...
Example 1: Basic Callbacks
// Simple callback
function greet(name, callback) {
console.log(`Hello, ${name}!`);
callback();
}
function sayGoodbye() {
console.log('Goodbye!');
}
greet('John', sayGoodbye);
// Output:
// Hello, John!
// Goodbye!
// Inline callback
greet('Jane', function() {
console.log('Have a great day!');
});
// Output:
// Hello, Jane!
// Have a great day!
// Arrow function callback
greet('Bob', () => console.log('See you later!'));
// Output:
// Hello, Bob!
// See you later!Example 2: Array Methods with Callbacks
const numbers = [1, 2, 3, 4, 5];
// forEach - executes callback for each element
numbers.forEach(function(num, index) {
console.log(`Index ${index}: ${num}`);
});
// map - transforms each element
const doubled = numbers.map(function(num) {
return num * 2;
});
console.log(doubled); // [2, 4, 6, 8, 10]
// filter - selects elements based on condition
const evens = numbers.filter(function(num) {
return num % 2 === 0;
});
console.log(evens); // [2, 4]
// reduce - reduces array to single value
const sum = numbers.reduce(function(acc, num) {
return acc + num;
}, 0);
console.log(sum); // 15
// find - finds first matching element
const found = numbers.find(function(num) {
return num > 3;
});
console.log(found); // 4
// With arrow functions (more concise)
const tripled = numbers.map(num => num * 3);
const odds = numbers.filter(num => num % 2 !== 0);
const product = numbers.reduce((acc, num) => acc * num, 1);
console.log(tripled); // [3, 6, 9, 12, 15]
console.log(odds); // [1, 3, 5]
console.log(product); // 120Example 3: Asynchronous Callbacks
// setTimeout - executes callback after delay
console.log('Start');
setTimeout(function() {
console.log('This runs after 2 seconds');
}, 2000);
console.log('End');
// Output:
// Start
// End
// This runs after 2 seconds
// setInterval - executes callback repeatedly
let count = 0;
const intervalId = setInterval(function() {
count++;
console.log(`Count: ${count}`);
if (count === 3) {
clearInterval(intervalId);
console.log('Stopped!');
}
}, 1000);
// Event listeners (in browser)
// document.getElementById('button').addEventListener('click', function() {
// console.log('Button clicked!');
// });
// Custom async function with callback
function fetchData(callback) {
console.log('Fetching data...');
setTimeout(function() {
const data = { id: 1, name: 'John', age: 30 };
callback(data);
}, 1000);
}
fetchData(function(result) {
console.log('Data received:', result);
});Example 4: Callback Hell and Solutions
// Callback Hell (Pyramid of Doom)
function step1(callback) {
setTimeout(() => {
console.log('Step 1 complete');
callback();
}, 1000);
}
function step2(callback) {
setTimeout(() => {
console.log('Step 2 complete');
callback();
}, 1000);
}
function step3(callback) {
setTimeout(() => {
console.log('Step 3 complete');
callback();
}, 1000);
}
// Nested callbacks (hard to read)
step1(function() {
step2(function() {
step3(function() {
console.log('All steps complete!');
});
});
});
// Better: Named functions
function onStep1Complete() {
step2(onStep2Complete);
}
function onStep2Complete() {
step3(onStep3Complete);
}
function onStep3Complete() {
console.log('All steps complete!');
}
step1(onStep1Complete);
// Best: Use Promises or async/await (modern approach)
// Covered in the Promises sectionExample 5: Custom Callback Functions
// Calculator with callback
function calculate(a, b, operation) {
return operation(a, b);
}
function add(x, y) {
return x + y;
}
function multiply(x, y) {
return x * y;
}
console.log(calculate(5, 3, add)); // 8
console.log(calculate(5, 3, multiply)); // 15
console.log(calculate(5, 3, (x, y) => x - y)); // 2
// Array processor with callback
function processArray(arr, callback) {
const result = [];
for (let i = 0; i < arr.length; i++) {
result.push(callback(arr[i], i, arr));
}
return result;
}
const nums = [1, 2, 3, 4, 5];
const squares = processArray(nums, num => num * num);
console.log(squares); // [1, 4, 9, 16, 25]
const indexed = processArray(nums, (num, idx) => `${idx}: ${num}`);
console.log(indexed); // ['0: 1', '1: 2', '2: 3', '3: 4', '4: 5']
// Error-first callback pattern (Node.js style)
function readFile(filename, callback) {
setTimeout(() => {
if (filename === 'error.txt') {
callback(new Error('File not found'), null);
} else {
callback(null, `Contents of ${filename}`);
}
}, 1000);
}
readFile('data.txt', function(error, data) {
if (error) {
console.error('Error:', error.message);
} else {
console.log('Success:', data);
}
});
readFile('error.txt', function(error, data) {
if (error) {
console.error('Error:', error.message); // Error: File not found
} else {
console.log('Success:', data);
}
});Key Points
- Callbacks are functions passed as arguments to other functions
- Used extensively in asynchronous programming (setTimeout, AJAX, events)
- Array methods (map, filter, reduce) use callbacks
- Can lead to "callback hell" when deeply nested
- Error-first callbacks are common in Node.js
- Modern alternatives: Promises and async/await