When async operations depend on each other, callbacks nest deeply. This creates "callback hell" or the "pyramid of doom."
getUser(id, (user) => {
getOrders(user.id, (orders) => {
getOrderDetails(orders[0].id, (details) => {
// Deeply nested, hard to read
});
});
});
This code is hard to read, maintain, and debug. Promises solve this.