Skip to main content

Передавання callback в іншу функцію

Щоб передати callback, вкажіть функцію як звичайний аргумент під час виклику іншої функції, а всередині приймальної функції викличте її за іменем параметра. Це можливо тому, що в JavaScript функції є значеннями (first-class citizens): їх можна присвоювати змінним, класти в масиви і передавати як аргументи.

Теорія

TL;DR

  • Callback передається як звичайний аргумент: doSomething(afterDone).
  • Передавайте посилання на функцію, без дужок. Дужки означають виклик і передадуть результат, часто undefined.
  • Усередині приймальної функції колбек викликають за іменем параметра: callback().
  • Можна передати іменовану функцію, анонімну функцію або стрілкову функцію прямо на місці виклику.
  • Приймальній функції байдуже, що саме робить callback: вона отримує поведінку ззовні.

Швидкий приклад

javascript
function doSomething(callback) { console.log('Doing something...'); callback(); // call the callback we were given } function afterDone() { console.log('Done!'); } doSomething(afterDone);

Вивід:

text
Doing something... Done!

Три способи передати callback

Форма запису різна, суть однакова: у параметр callback потрапляє функція.

javascript
// 1. Іменована функція, передаємо посилання на неї function afterDone() { console.log('Done!'); } doSomething(afterDone); // 2. Анонімна функція прямо в аргументі doSomething(function () { console.log('Done!'); }); // 3. Стрілкова функція, найкоротший запис doSomething(() => { console.log('Done!'); });
СпосібКоли зручний
Іменована функціяЛогіку перевикористовують у кількох місцях, її легко протестувати окремо
Анонімна functionПотрібен власний this або arguments усередині колбека
Стрілкова функціяКороткий одноразовий обробник, this береться із зовнішньої області

Передавання аргументів у callback

Приймальна функція сама вирішує, з якими аргументами викликати колбек. Викликач лише описує, що робити з цими значеннями.

javascript
function doSomething(callback) { const result = 42; callback(result); // pass data into the callback } doSomething(value => { console.log('Got', value); // Got 42 });

Якщо треба «зафіксувати» власні аргументи заздалегідь, загорніть виклик у стрілкову функцію або застосуйте bind.

javascript
function greet(name) { console.log('Hello, ' + name); } doSomething(() => greet('Maria')); // wrapper keeps the argument doSomething(greet.bind(null, 'Oleh')); // the same via bind

Виклик замість передавання: головна пастка

afterDone це функція, afterDone() це вже її результат. Дужки в аргументі виконують функцію негайно, і приймальна функція отримає не поведінку, а значення, яке та повернула.

javascript
doSomething(afterDone); // correct: pass the function itself doSomething(afterDone()); // wrong: runs now and passes undefined

Той самий принцип працює для будь-якого API, що приймає колбек: setTimeout(fn, 100), addEventListener('click', fn), array.map(fn).

Захист від відсутнього колбека

Якщо параметр необов'язковий, перевірте його перед викликом або дайте значення за замовчуванням, інакше отримаєте TypeError: callback is not a function.

javascript
function doSomething(callback = () => {}) { console.log('Doing something...'); callback(); } doSomething(); // works even without an argument

Типові помилки

  • Передавати afterDone() замість afterDone: функція виконається одразу, а в параметр потрапить undefined.
  • Ставити дужки в setTimeout(sayHi(), 100) і дивуватися, що таймер нічого не робить.
  • Викликати колбек, не перевіривши, що його справді передали, і отримувати TypeError.
  • Передавати метод об'єкта напряму, obj.handler, і втрачати this. Рятує стрілкова обгортка або bind.
  • Очікувати, що значення з асинхронного колбека буде доступне одразу після виклику функції: воно з'явиться лише тоді, коли колбек справді виконається.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.