Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке "callback hell"?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Callback hell** - це ситуація, коли в коді використовується багато вкладених callback-функцій, через що код стає важким для читання, підтримки і практично неможливим для налагодження. **Ключове:** callback hell - це «пірамида жаху», коли колбеки викликають інші колбеки.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Callback hell** - це ситуація, коли в коді використовується **багато вкладених callback-функцій**, через що код стає: - важким для читання, - складним для підтримки, - і практично неможливим для налагодження. Простіше кажучи: > "Callback hell" - це **пекло для розробника**, коли колбеки викликають інші колбеки, > утворюючи «піраміду жаху». --- ## Приклад «пекла з колбеків» ```javascript getUser('tim', (user) => { getPosts(user.id, (posts) => { getComments(posts[0].id, (comments) => { saveToDB(comments, (result) => { console.log('Готово!'); }); }); }); }); ``` Тут: - Кожна функція чекає завершення попередньої, - Колбеки вкладені один в одного, - Відступи ростуть праворуч, - Помилки складно ловити, - І код перетворюється на «ліс» із дужок. Це і є **callback hell**. --- ## Чому це погано | Проблема | Опис | |---|---| | **Погана читабельність** | Вкладені рівні роблять код візуально важким | | **Складно обробляти помилки** | Кожному колбеку потрібна своя перевірка `if (err) ...` | | **Залежності ланцюжком** | Кожна операція чекає попередню | | **Складне налагодження** | Винятки губляться, stack trace довгий | | **Неможливо повторно використати код** | Все "зашите" у вкладені анонімні функції | --- ## Звідки він береться Проблема характерна для **асинхронного JavaScript** часів до ES6, коли все будувалося на колбеках: - Робота з API: `XMLHttpRequest` - Таймери: `setTimeout` - Події: `addEventListener` - Node.js до Promise API --- ## Як виглядав старий асинхронний код ```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 надіслано!'); }); }); }); ``` Все працює, але виглядає жахливо - складно підтримувати, тестувати і розширювати. --- ## Як уникнути callback hell ### 1. Використовувати **іменовані функції** Це хоча б "випрямляє" код: ```javascript function handleUser(user) { getPosts(user.id, handlePosts); } function handlePosts(posts) { getComments(posts[0].id, handleComments); } function handleComments(comments) { console.log('Готово!'); } getUser('tim', handleUser); ``` --- ### 2. Використовувати **Promise** ```javascript getUser('tim') .then(getPosts) .then(getComments) .then(saveToDB) .then(() => console.log('Готово!')) .catch(console.error); ``` Код став лінійним, читається зверху вниз, без вкладеності. --- ### 3. Використовувати **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('Готово!'); } catch (err) { console.error(err); } } run(); ``` Тепер код виглядає як синхронний, але працює асинхронно. Жодних «пірамід жаху». --- ## Проста аналогія > Callback hell - це як готувати вечерю, де кожен крок вимагає дзвінка другу, > а той дзвонить ще комусь, і всі чекають один одного, > поки не вийде «піраміда дзвінків». --- ## ПІДСУМОК | Термін | Опис | |---|---| | **Callback hell** | Ситуація з глибокою вкладеністю callback-функцій | | **Причина** | Асинхронний код, побудований на колбеках | | **Недоліки** | Погана читабельність, складне налагодження, дублювання логіки | | **Рішення** | Promise, async/await, іменовані функції, декомпозиція |Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.