Suggest an editImprove this articleRefine the answer for “What is "callback hell"?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**Callback hell** is a situation where the code uses many nested callback functions, which makes it hard to read, hard to maintain, and nearly impossible to debug. **Key point:** callback hell is a "pyramid of doom" where callbacks call other callbacks.Shown above the full answer for quick recall.Answer (EN)Image**Callback hell** is a situation where the code uses **many nested callback functions**, which makes the code: - hard to read, - hard to maintain, - and nearly impossible to debug. In other words: > "Callback hell" is **a developer's nightmare**, where callbacks call other callbacks, > forming a "pyramid of doom". --- ## An example of a "callback hell" ```javascript getUser('tim', (user) => { getPosts(user.id, (posts) => { getComments(posts[0].id, (comments) => { saveToDB(comments, (result) => { console.log('Done!'); }); }); }); }); ``` Here: - Each function waits for the previous one to finish, - Callbacks are nested inside one another, - Indentation grows to the right, - Errors are hard to catch, - And the code turns into a "forest" of braces. This is **callback hell**. --- ## Why this is bad | Problem | Description | |---|---| | **Poor readability** | Nested levels make the code visually heavy | | **Hard to handle errors** | Every callback needs its own `if (err) ...` check | | **Chained dependencies** | Each operation waits for the previous one | | **Hard to debug** | Exceptions get lost, the stack trace is long | | **Cannot reuse code** | Everything is "baked into" nested anonymous functions | --- ## Where it comes from This problem is typical of **asynchronous JavaScript** from before ES6, when everything was built on callbacks: - Working with APIs: `XMLHttpRequest` - Timers: `setTimeout` - Events: `addEventListener` - Node.js before the Promise API --- ## What old asynchronous code looked like ```javascript fs.readFile('user.json', (err, data) => { if (err) throw err; getPosts(JSON.parse(data).id, (err, posts) => { if (err) throw err; sendEmail(posts, (err) => { if (err) throw err; console.log('Email sent!'); }); }); }); ``` It all works, but it looks awful - hard to maintain, test, and extend. --- ## How to avoid callback hell ### 1. Use **named functions** This at least "straightens out" the code: ```javascript function handleUser(user) { getPosts(user.id, handlePosts); } function handlePosts(posts) { getComments(posts[0].id, handleComments); } function handleComments(comments) { console.log('Done!'); } getUser('tim', handleUser); ``` --- ### 2. Use **Promise** ```javascript getUser('tim') .then(getPosts) .then(getComments) .then(saveToDB) .then(() => console.log('Done!')) .catch(console.error); ``` The code becomes linear, reads top to bottom, with no nesting. --- ### 3. Use **async / await** ```javascript async function run() { try { const user = await getUser('tim'); const posts = await getPosts(user.id); const comments = await getComments(posts[0].id); await saveToDB(comments); console.log('Done!'); } catch (err) { console.error(err); } } run(); ``` Now the code looks synchronous, but runs asynchronously. No more "pyramids of doom". --- ## A simple analogy > Callback hell is like cooking dinner where every step requires calling a friend, > and that friend calls someone else, and everyone waits on each other, > until you end up with a "pyramid of calls". --- ## SUMMARY | Term | Description | |---|---| | **Callback hell** | A situation with deeply nested callback functions | | **Cause** | Asynchronous code built on callbacks | | **Downsides** | Poor readability, hard debugging, duplicated logic | | **Solutions** | Promise, async/await, named functions, decomposition |For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.