Uvod u JavaScript Ajax
Ajax (Asynchronous JavaScript And XML) je tehnologija koja je praktično označila prekretnicu u razvoju web aplikacija. Ono što popularno zovemo Web 2.0, tehnički je omogućeno upravo Ajaxom.
O čemu se radi? Način funkcionisanja web aplikacija se može opisati kao uzastopna komunikacija klijenta i servera.
- stranica se učita u korisnikov web čitač
- korisnik "nešto radi" na stranici - popunjava polja, bira opcije...
- JavaScript program reaguje na akcije korisnika (web stranica menja izgled, proveravaju se podaci...)
- kada korisnik završi rad, podaci se prosleđuju serveru u obliku novog zahteva
- na serveru se podaci obrađuju (rad sa bazom podataka i sl.), a na osnovu zahteva generiše i novu stranicu sa rezultatima
- nova stranica se učitava u korisnikov web čitač i ceo proces se ponavlja...
Na taj način stranicu-po-stranicu korisnik i web aplikacija dolaze do cilja.
Kao što znamo, podaci se uvek prosleđuju nekom konkretnom "programu" na serveru. Na našem sajtu smo se opredelili za PHP, pa bi to u našem slučaju uvek bila neka zasebna PHP stranica. Da li će jedna ista PHP stranica da obrađuje više različitih zahteva sa podacima ili će se za svaki zahtev praviti zaseban PHP program, zavisi od programera.
Koja god tehnologija na serveru da se koristi (dakle čak i ne mora da bude PHP), izlaz koji generiše program na serveru tumači se kao odgovor servera klijentu, tj. kao neka nova stranica sa podacima. Server će odgovor najčešće "spakovati" u obliku HTML-a, ali to može biti i običan tekst, slika i sl. pri čemu je ostavljeno da korisnikov web čitač tumači dobijeni podatak samostalno ili na osnovu meta-podataka koje dobija sa servera.
Ono što korisnicima smeta u klasičnim web aplikacijama je upravo to što se posle svakog slanja podataka serveru, uvek vrši učitavanje nove stranice u web čitaču.
To je problem koji se rešava korišćenjem Ajax tehnologije. Suštinski Ajax omogućava komunikaciju sa serverom "u pozadini". Dakle podaci se šalju na server, potom se rezultati prihvataju sa servera i to sve bez učitavanja nove stranice. Korisnik tako ne mora ni da primeti da se nešto događa.
Ovo je otvorilo put tzv. single page web aplikacijama, kod kojih se sve dešava na jednoj istoj stranici koja se menja zavisno od rezultata korisnikovih aktivnosti. Međutim, promena nije samo estetska sa svrhom poboljšanja korisničkog iskustva:
- smanjuje se potreba za korišćenjem kolačića (cookie), pošto se sve odvija na jednoj istoj stranici
- veća brzina komunikacije - server može slati smao "suve" podatke, ne mora da generiše čitavu stranicu
- komunikacija je asinhrona, što znači da se korisniku ne "koči" rad dok se u pozadini web čitač povezuje sa serverom
Ajax se "aktivira" kreiranjem posebnog XMLHttpRequest objekta u JavaScriptu. Ovaj objekat može da šalje podatke na server pomoću standardnih HTTP zahteva (najčešće GET ili POST), kao i da dočekuje odgovor koji može biti formatiran kao XML ili običan tekst. Server preuzima podatke na isti način kao što bi to radio u bilo kojoj drugoj situaciji. Rezultat je bilo šta što programer želi - pa makar i "klasični" HTML.
Kreiranje Ajax zahteva
Ceo postupak slanja zahteva i primanja rezultata poveren je jednom specijalnom objektu: XMLHttpRequest. Da bismo bilo šta mogli da radimo sa Ajaxom, prvo moramo da kreiramo instancu tog objekta:
var zahtev = new XMLHttpRequest();
U našem JavaScript programu možemo za svaki poziv kreirati novi objekat ili jednom napravljen objekat koristiti da uputimo više zahteva. Sve zavisi od našeg stila programiranja. Sa svojstvima, metodima i događajima ovog objekta ćemo se detaljno upoznati kasnije.
Za sada, hajde da vidimo šta nam je minimalno potrebno za upućivanje jednog Ajax zahteva. Kada smo napravili Ajax objekat, možemo da ga koristimo. Neka svojstva (metodi) ovog objekta su bitna za slanje, a neka za primanje podataka.
Prva stvar vezana za upućivanje zahteva je njegova inicijalizacija. U stvari ovde praktično definišemo sam zahtev:
zahtev.open(metod, URL);
- metod - zadaje se HTTP metod upućivanja zahteva serveru, najčešće su to vrednosti "GET" i "POST" (baš velikim slovima)
- URL - zadaje se putanja do programa na serveru od koga se očekuje rezultat. Ako je u pitanju GET zahtev, onda URL obično sadrži i parametre, odnosno podatke koje šaljemo serveru.
Ovako pripremljenom zahtevu možemo podesiti još neke stvari (npr. možemo mu definisati zaglavlje metodom setRequestHeader(), ako je potrebno), ali generalno, zahtev je i ovako (u većini jednostavnijih slučajeva) praktično spreman za slanje:
zahtev.send();
zahtev.send(podaci);
Podaci mogu i ne moraju da se zadaju. Kada koristimo GET zahtev, obično pozivamo ovaj metod bez parametara.
- podaci - ono što se šalje uz zahtev, obično kada je u pitanju "POST" HTTP metod.
Ne zaboravite, posle poziva ovog metoda, JavaScript program prosto nastavlja sa izvršavanjem, kao da se ništa nije desilo. Kada stigne odgovor servera, poziva se neka od callback funkcija koje smo definisali kao event handlere za događaje Ajax objekta.
Dobijanje odgovora sa servera
Negde između kreiranja XMLHttpRequest objekta i slanja zahteva pozivanjem send() metode bismo morali da definišemo funkciju koja "hvata" odgovor servera. Ovo je obična callback funkcija, koja nema čak ni parametre.
Postoji nekoliko definisanih događaja koji "okidaju" kada stignu podaci sa servera. Istorijski, najkorišćeniji je onreadystatechange (svojevremeno je to bio i jedini događaj), koji "okida" svaki put kada se promeni vrednost svojstva readyState. Ovo svojstvo je numeričkog tipa i menja mu se vrednost zavisno od toga u kom "statusu" je trenutno naš zahtev. Zbog toga, događaj "readyState Change" okida nekoliko puta tokom slanja/primanja podataka, a na nama je da u funkciji proverimo zbog čega (tj. koja je vrednost svojstva readyState).
zahtev.onreadystatechange = function() {
if (zahtev.readyState == 4) {
// stigao rezultat sa servera
}
};
Ipak, za početak ćemo se držati novijeg događaja onload, koji se aktivira kada dobijemo odgovor sa servera (i nije došlo do greške).
zahtev.onload = function() {
// obrada podataka sa servera
};
Ostaje još samo da vidimo kako da pristupimo konkretnim podacima. Ajax objekat ima još dva značajna svojstva, a to su responseText i responseXML. U prvom se nalazi "sirov" rezultat, onako kako ga je server poslao, dok se u drugom nalazi XML struktura, ali samo ako je odgovor servera bio u tom obliku i to baš-baš ispravan (u parsiranju XML-a se čak ni najmanje greške ne tolerišu, za razliku od recimo HTML-a).
Način na koji ćemo obrađivati podatke zavisi samo od nas - kako smo odredili da server "pakuje" podatke i kako želimo da ih iščitavamo. Da li ćemo koristiti String funkcije i regularne izraze da "čupamo" delove teksta ili će podaci biti u nekoj "zvaničnoj" strukturi poput JSON, XML ili HTML podataka, određeno je našim afinitetima i time šta je u toj situaciji najefikasnije sa stanovišta brzine prenosa podataka i lakoće obrade.
zahtev.onload = function() {
console.log( zahtev.responseText );
};
Kao što vidite - nije ništa komplikovano. Ovde smo objasnili najosnovniji način rada sa Ajax tehnologijom. Naravno, ima toga još, ali suština je upravo ovo što ste pročitali.
Jednostavan Ajax poziv
Hajde da sada sve sklopimo u jednu celinu. Ovo je ilustracija kako bi mogao da izgleda jedan Ajax poziv, na osnovu svega što smo do sada napisali.
<script>
function poziv() {
var zahtev = new XMLHttpRequest();
zahtev.onload = function() {
document.getElementById("okvir").innerHTML = zahtev.responseText;
}
var x = document.getElementById("polje").value;
zahtev.open("GET", "primer.php?tip=text&podatak=" + x);
zahtev.send();
}
</script>
<div>
<input id="polje" type="text" value="" />
<input type="button" value="klikni" onclick="poziv()" />
</div>
<div id="okvir"></div>
U HTML delu vidimo jedno polje za običan tekstualni unos i jedno dugmence. Polje je identifikovano kao "polje", da bismo kasnije mogli da mu pristupimo iz JavaScripta, dok je u dugmencetu zadato da se poziva funkcija poziv() u trenutku kada se klikne na njega.
U funkciji poziv() se najpre kreira Ajax objekat (tačnije XMLHttpRequest objekat) zahtev. Sve što u funkciji radimo sa Ajaxom, radićemo upravo preko ovog objekta.
Sledeće, definišemo callback funkciju, koja se poziva kada nastupi Ajax on load događaj, tj. kada se desi da uspešno dobijemo rezultat sa servera. Dakle, deluje malo naopako - prvo pravimo šta se dešava kada rezultat stigne, a tek onda šaljemo zahtev. U ovoj unutrašnjoj funkciji radimo samo jednu stvar - popunjavamo sadržaj <div> elementa "okvir" tekstualnim rezultatom koji smo dobili sa servera. Rezultat se nalazi u svojstvu responseText našeg Ajax objekta, i njega u celini ubacujemo u <div> blok.
Ok, da se vratimo na slanje zahteva. Pošto smo definisali callback funkciju, čitamo vrednost <input> polja "polje" i ubacujemo je u promenljivu x.
Onda definišemo zahtev koji se prosleđuje, koristeći Ajaxov metod open(). Najpre zadajemo da će se zahtev prosleđivati kao HTTP GET zahtev. Onda zadajemo URL na koji se zahtev upućuje. U ovom slučaju je naveden neki PHP program po imenu primer.php, kome prosleđujemo dva parametraČ tip sa vrednošću "text" i podatak sa vrednošću koja je preuzeta iz <input> polja - promenljiva x.
Konačno, zaista upućujemo zahtev, koristeći Ajaxov metod send(). Pošto je u pitanju GET poziv, ovde nema nikakvih dodatnih podataka.
Ostalo je da pogledate i kako Ajax funkcioniše u praksi. Pripremili smo vam jedan "živi" primer, detaljno komentarisan, a objašnjeno je i kako smo sastavili PHP koji funkcioniše na serveru.
- Mozilla Developers Network, AJAX Getting Started
- Mozilla Developers Network, XMLHttpRequest
- Mozilla Developers Network, Using XMLHttpRequest
- w3.org, Method Definitions
- R. Ferguson, C. Heilmann (2013): Beginning JavaScript with DOM Scripting and Ajax, Apress, New York