Callback

Funkcja przekazana jako argument do innej funkcji, która wywoła ją w odpowiednim momencie. Często używana przy operacjach asynchronicznych.

Callback (funkcja zwrotna) to funkcja, którą przekazujesz jako argument do innej funkcji, żeby ta wywołała ją w wybranym przez siebie momencie. Zamiast pytać co chwilę „już? już skończyłeś?”, mówisz po prostu: „jak skończysz, to odpal to”. Reszta to detale.

Jak to działa

W językach, w których funkcje są first-class citizens (czyli można je trzymać w zmiennych i podawać dalej — jak w JavaScript, Pythonie czy Go), funkcja to taka sama wartość jak liczba czy string. Możesz ją więc wręczyć innej funkcji, a ta zdecyduje, kiedy ją uruchomić: po kliknięciu, po pobraniu danych z serwera, po przejściu przez każdy element tablicy albo dopiero po odliczeniu timera.

Callbacki świecą najjaśniej przy operacjach asynchronicznych. Gdy odpytujesz API albo czytasz plik, program nie może stać i czekać — robi swoje, a callback odpala się dopiero wtedy, gdy wynik faktycznie przyjdzie. Dzięki temu kod się nie blokuje.

Przykład z praktyki

Klasyk z JavaScriptu — metoda addEventListener przyjmuje callback, który wykona się po kliknięciu:

  • button.addEventListener('click', () => console.log('kliknięto!'))

Albo przetwarzanie tablicy, gdzie map wywołuje twój callback dla każdego elementu:

  • [1, 2, 3].map((x) => x * 2) zwróci [2, 4, 6]

W Node.js przez lata królowała konwencja error-first callback: pierwszym argumentem jest błąd (albo null), drugim dane — fs.readFile('plik.txt', (err, data) => { ... }).

Na co uważać

Gdy callbacki zagnieżdżasz jeden w drugim, dostajesz słynne callback hell (zwane też „piramidą zagłady”) — kod ucieka w prawo, a wcięcia robią się coraz głębsze i nieczytelne. Drugi częsty błąd to nie wywołać callbacku w ogóle albo wywołać go dwa razy — wtedy program cicho się zawiesza lub robi coś dwukrotnie. Dlatego w nowoczesnym JS callbacki przy asynchroniczności w dużej mierze ustąpiły miejsca Promise i składni async/await, które czyta się liniowo. Ale callback nie umarł — wciąż jest fundamentem event handlerów, metod tablicowych i wielu API.

Pojęcia powiązane

Higher-order function, Promise, async/await, event loop, event handler, closure (domknięcie), funkcja anonimowa, lambda.