Callback funkcije u JavaScriptu
Callback je mehanizam, poznat i u drugim jezicima, koji omogućava da se funkcija prosledi kao parametar, da bi kasnije bila pozvana po potrebi. Ova praksa ima korene u funkcionalnom programiranju gde je prosleđivanje funkcija kao parametara sasvim uobičajena stvar.
Jedan od najboljih primera korišćenja callback funkcije su metodi Array objekta. Ovaj objekat pruža mogućnost prolaska kroz elemente niza, njihovog ispitivanja ili sortiranja, a sve to uz mogućnost da sam programer napravi šta se dešava sa pojedinačnim elementima. Drugi primer callback funkcije je zadavanje tajmera koji poziva callback funkciju posle određenog zadatog vremena.
Ono u čemu je web specifičan je što, ako radimo malo složeniju aplikaciju, često dolazimo u situaciju da na sred izvršavanja programa moramo da čekamo podatke sa servera. Tada moramo da zaustavimo rad, a kada podaci stignu, sve može da se nastavi. Praktično, moramo da "prepolovimo" svoj program na deo koji "poziva" i deo koji "dočekuje" podatke. U momentu kada server odgovori, poziva se callback funkcija koja služi kao početna tačka za nastavak rada. Ova tehnika će detaljnije biti obrađena kada budemo razmatrali Ajax tehnologiju u delu koji se bavi web aplikacijama.
U najvećem broju slučajeva koristimo callback funkcije kao funkcije za obradu događaja (event handleri). To su funkcije koje se aktiviraju kada se u web aplikaciji nešto "dogodi" (najčešće kao posledica korisnikove aktivnosti).
Sve će biti mnogo jasnije kada pogledamo par primera.
Callback primeri
Tajmer
function fun() // callback funkcija
{
// menja boju pozadine dokumenta
document.body.style.backgroundColor = "#003";
}
window.setTimeout(fun, 4000); // posle 4 sec poziva callback funkciju
Ovo je jednostavan primer u kome smo postavili tajmer i zadali funkciju fun() kao callback, koja se poziva posle 4 sekunde (4000 milisekundi). Ovo je tipičan primer pauziranja izvršavanja programa - sve se završi, a onda se, 4 sekunde kasnije, ponovo aktivira. Inače funkcija promeni boju pozadine dokumenta u tamno plavu.
Obratite pažnju kako navodimo callback funkciju u metodu setTimeout(). Navodi se samo naziv funkcije: setTimeout(fun, 4000). Nikako ne navodimo funkciju sa zagradama - to bi bio poziv funkcije. Dakle, pogrešno bi bilo: setTimeout(fun(), 4000).
Ok, i ovde postoje "napredni" izuzeci - moguće je zadati i poziv funkcije, ali pod uslovom da je to funkcija višeg reda, koja kao rezultat vraća našu callback funkciju. Ovo je već malo naprednija tehnika i zahteva odlično poznavanje funkcionalnog programiranja i lambda izraza.
Niz
var niz = [14, 5, 6, -2, 7];
if (niz.every(veci)) { // ovde zadajemo callback funkciju
console.log("Svi elementi su veći od nule.");
}
function veci(a) // deklaracija callback funkcije
{
return a > 0;
}
Svaki Array objekat ima metod every() koji je samo jedan od metoda kojim se "obrađuju" elementi niza. Konkretno ovaj metod koristimo ako je potrebno da se ispita da li svaki pojedini element zadovoljava neki uslov. To znači da metod auitomatski prolazi kroz sve elemente niza i ako je svaki zadovoljio, kao rezultat vraća vrednost true.
Ideja je da sam objekat Array obezbedi najbrži mogući prolazak kroz niz, a da programer napravi callback funkciju koja za jednu prosleđenu vrednost vraća rezulatat da li ta vrednost zadovoljava uslov ili ne. Array objekat za svaki elemenat niza poziva tu funkciju i prikuplja dobijene rezultate.
U ovom slučaju je funkcija veci() u ulozi callback funkcije, pošto je zadajemo kao parametar metodu every().
Event handler
obj = document.createElement("div");
obj.innerHTML = "BLOK";
obj.addEventListener("click", klik); // definišemo event handler
document.body.appendChild(obj);
function klik() { // deklaracija event handler funkcije
this.style.color = "#f00";
this.style.backgroundColor = "#ffc";
}
U gornjem primeru, kreirali smo DIV blok, zadali mu tekst "BLOK" i dodali funkciju klik() koja reaguje na događaj "click" (klik mišem), pomoću metoda addEventListener(). Samim tim funkcija klik() postaje event handler, koji "opaljuje" u trenutku kada korisnik klikne na DIV blok.
U funkciji klik() se vidi da će DIV blok, kada se klikne na njega, promeniti boju teksta i boju pozadine. Nemojte da vas zbunjuje objekat this. njega ćemo objasniti malo kasnije. Za sada je dovoljno da znate da se u ovom slučaju this odnosi na kliknuti objekat.
- J. Resig, B. Bibeault (2013): Secrets of the JavaScript Ninja, Manning Publications, New York
- A. Rauschmayer (2014): Speaking JavaScript, O’Reilly, Sebastopol