JavaScript Promises Tutorial - Section 1: Introduction
A callback is a function passed as an argument to another function, to be executed later.
function greet(name, callback) {
console.log('Hello ' + name);
callback();
}
greet('Alice', function() {
console.log('Callback executed!');
});
// Output:
// Hello Alice
// Callback executed!
Callbacks were the original way to handle async operations in JavaScript:
setTimeout(function() {
console.log('This runs after 2 seconds');
}, 2000);
const fs = require('fs');
fs.readFile('data.txt', 'utf8', function(error, data) {
if (error) {
console.error('Error reading file:', error);
return;
}
console.log('File contents:', data);
});
Pattern: function(error, result)
function fetchUser(id, callback) {
setTimeout(() => {
if (id < 0) {
callback(new Error('Invalid ID'), null);
} else {
callback(null, { id: id, name: 'User ' + id });
}
}, 1000);
}
fetchUser(1, (error, user) => {
if (error) {
console.error('Error:', error.message);
return;
}
console.log('User:', user);
});
function loadImage(url, onSuccess, onFailure) {
const img = new Image();
img.onload = () => onSuccess(img);
img.onerror = () => onFailure(new Error('Failed to load'));
img.src = url;
}
loadImage(
'photo.jpg',
(img) => console.log('Loaded:', img),
(error) => console.error('Error:', error)
);
When you need to perform multiple async operations in sequence, callbacks get nested:
getUserData(userId, (error, user) => {
if (error) {
console.error(error);
return;
}
getOrders(user.id, (error, orders) => {
if (error) {
console.error(error);
return;
}
getOrderDetails(orders[0].id, (error, details) => {
if (error) {
console.error(error);
return;
}
getShippingInfo(details.shippingId, (error, shipping) => {
if (error) {
console.error(error);
return;
}
console.log('Finally got shipping info:', shipping);
});
});
});
});
Different libraries use different patterns:
function getData(callback) {
setTimeout(() => {
callback('data');
}, 1000);
}
const result = getData((data) => {
return data; // This return goes nowhere!
});
console.log(result); // undefined
Hard to combine multiple async operations:
You give your callback to another function and trust it will:
Promises were introduced to solve these problems:
getUserData(userId)
.then(user => getOrders(user.id))
.then(orders => getOrderDetails(orders[0].id))
.then(details => getShippingInfo(details.shippingId))
.then(shipping => console.log('Shipping info:', shipping))
.catch(error => console.error('Error:', error));
Benefits:
In the next lesson, we'll introduce Promises - the modern solution to callback hell!