Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Callback-функція». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Callback-функція це функція, яку передають як аргумент в іншу функцію, щоб та викликала її пізніше, коли завершить свою роботу.** Колбеки дозволяють передавати саме поведінку, а не лише дані, і використовуються, щоб виконати дію після події, операції чи асинхронного процесу: завантаження даних, таймера, кліка. ```javascript function fetchData(callback) { setTimeout(() => { const data = 'Data from the server'; callback(data); // викликаємо передану функцію }, 1000); } fetchData(result => console.log(result)); // "Data from the server" ``` **Ключове:** callback це спосіб передавати поведінку і керувати послідовністю виконання коду, особливо в асинхронних операціях.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Callback-функція це функція, яку передають як аргумент в іншу функцію і яка викликається пізніше, коли та завершить свою роботу.** Зазвичай колбеки використовують, щоб виконати дію після події, операції або асинхронного процесу, наприклад після завантаження даних, спрацювання таймера чи кліка. ## Теорія ### TL;DR - Callback це функція-аргумент, яку викликає не ваш код, а та функція, якій ви її віддали. - Це можливо тому, що в JavaScript функції є значеннями першого класу: їх можна передавати й повертати. - Колбеки бувають синхронні (`map`, `filter`, `forEach`) і асинхронні (`setTimeout`, обробники подій, запити). - Передавайте посилання на функцію, а не її виклик: `setTimeout(fn, 100)`, а не `setTimeout(fn(), 100)`. - Багато вкладених колбеків перетворюються на callback hell, який лікують Promise і `async/await`. ### Швидкий приклад ```javascript function fetchData(callback) { setTimeout(() => { const data = 'Data from the server'; callback(data); // викликаємо передану функцію }, 1000); } fetchData(result => console.log(result)); // "Data from the server" ``` `fetchData` нічого не знає про те, що робитиме з результатом: цю частину поведінки вона отримує ззовні. ### Чому це працює: функції як значення У JavaScript функція це звичайне значення, тому її можна присвоїти змінній, покласти в масив чи передати в іншу функцію. Функцію, яка приймає або повертає іншу функцію, називають функцією вищого порядку (higher-order function), а передану функцію, callback. ```javascript const numbers = [1, 2, 3]; // map це функція вищого порядку, стрілкова функція всередині це callback const doubled = numbers.map(n => n * 2); // [2, 4, 6] ``` ### Синхронні та асинхронні колбеки Синхронний callback викликається одразу, у межах того самого виклику функції. Асинхронний потрапляє в чергу і виконається пізніше, коли call stack звільниться. ```javascript // синхронний: виконається до наступного рядка [1, 2, 3].forEach(n => console.log(n)); // асинхронний: виконається після всього синхронного коду setTimeout(() => console.log('later'), 0); console.log('now'); // порядок у консолі: 1, 2, 3, now, later ``` ### Обробка помилок: стиль error-first У Node.js історично склалася домовленість: перший параметр колбека це помилка, а дані йдуть далі. Так викликач може обробити збій у тому самому місці, де отримує результат. ```javascript function loadUser(id, callback) { setTimeout(() => { if (!id) { callback(new Error('id is required')); return; } callback(null, { id, name: 'Maria' }); }, 100); } loadUser(7, (err, user) => { if (err) { console.error(err.message); return; } console.log(user.name); // Maria }); ``` ### Callback hell і сучасна альтернатива Коли одна асинхронна операція залежить від іншої, колбеки починають вкладатися один в одний, і код зсувається вправо «драбинкою». Це і називають callback hell: його важко читати й ще важче обробляти в ньому помилки. ```javascript loadUser(7, (err, user) => { loadOrders(user.id, (err, orders) => { loadItems(orders[0].id, (err, items) => { console.log(items); // вкладеність росте з кожним кроком }); }); }); ``` Сучасне рішення це Promise і `async/await`: та сама послідовність записується пласко, а помилки ловляться одним `try/catch`. ```javascript async function showItems() { try { const user = await loadUser(7); const orders = await loadOrders(user.id); const items = await loadItems(orders[0].id); console.log(items); } catch (err) { console.error(err.message); } } ``` ### Типові помилки - Передавати результат виклику замість самої функції: `setTimeout(sayHi(), 100)` виконає `sayHi` негайно і передасть таймеру `undefined`. Правильно: `setTimeout(sayHi, 100)`. - Очікувати, що значення, отримане в асинхронному колбеку, буде доступне одразу після виклику функції: воно з'явиться лише тоді, коли колбек справді виконається. - Ігнорувати перший аргумент з помилкою в error-first колбеках і продовжувати роботу з порожніми даними. - Викликати callback двічі (і на успіху, і на помилці), бо забули `return` після обробки збою. - Втрачати `this`, передаючи метод об'єкта як callback: `element.addEventListener('click', obj.handler)` викличе метод з іншим `this`. Рятує стрілкова функція або `bind`. - Будувати глибокі вкладені колбеки там, де давно можна взяти Promise чи `async/await`.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.