AJAX, jeho schopnosti a komplikace
Jedním z pojmů často používaných v souvislosti s webovými aplikacemi je AJAX. Zkratka sice znamená Asynchronous JavaScript and XML, ale v praxi se často ani nepoužívá asynchronně, ani se nepřenáší XML. Běžně jím tedy označujeme obecně komunikaci javascriptové aplikace se serverem. Umožňuje získávat data za běhu aplikaci, bez nutnosti znovu načítat stránku.
Základní aplikační rozhraní se mezi různými prohlížeči liší. Tady samozřejmě nastupuje jQuery, kdy stačí používat ve všech prohlížečích stejné metody. Dále může probíhat pouze jediný požadavek na server, při pokusu odeslat další během vyřizování předchozího musí ten nový čekat.
Nelze také zapomenout na bezpečnostní omezení – většina požadavků podléhá tzv. same-origin policy, tedy omezení přístupu jen na stejné schéma (protokol), server a port. Existují metody, jak toto omezení obejít, ale obecně platí a nelze libovolně sahat na cizí zdroje.
A konečně pozor na „svody“ použít synchronní komunikaci, i když tu tato možnost je a může být někdy užitečná. Je to sice implementačně jednodušší, ale aplikace během vyřizování požadavku čeká na data ze serveru a nemůže tedy obsluhovat události. Tedy uživatel se pak může „uklikat“ a ono to nic nedělá.
Změna HTML ve stránce
Relativně jednoduchou, ale přitom velmi užitečnou operací je změna kusu HTML kódu (fragmentu, snippetu) ve stránce. Výhoda je v tom, že není nutno nějak specificky řešit implementaci změn ve stránce na základě dat ze serveru. Prostě se pošle požadavek, ze serveru přijdou data a ta se do stránky zapracují.
Některé webové frameworky, například Nette, umožňují vyřešit tuto operaci na serverové straně velmi jednoduše. Framework podle hlavičky (X-Requested-With: XMLHttpRequest
) sám pozná, kdy byl požadavek odeslán z JavaScriptu a pošle jen příslušný kus stránky.
Požadavky se posílají typicky na základě nějakého podnětu uživatele (kliknutí, stisk klávesy…) či jiné události, například periody časovače. Obecně na tom příliš nezáleží, jen je potřeba dát pozor na to, aby se požadavky na server neposílaly zbytečně často.
var reqRun = false; function sendRequest() { if (reqRun) return; reqRun = true; $.get('content.php', null, function(data) { $('#content').html(data); }, 'html') .always(function() { reqRun = false; }); }
Ve stránce máme box s identifikátorem content
, jehož obsah se bude měnit podle dat ze serveru. V javascriptovém kódu deklarujeme proměnnou reqRun
, která brání opětovnému odeslání požadavku, dokud není dokončen. Uvnitř funkce sendRequest()
, v níž je veškerý kód pro odesílání požadavku, se nejprve proměnná otestuje (pokud je nastavena, končí se) a pak se nastaví na true
.
Dalším krokem je vlastní odeslání požadavku. Tady se používá jednoduchá metoda get()
, určená pro požadavky s HTTP metodou GET. Prvním parametrem je zde URL, druhý je prázdný (tam mohou být parametry požadavku, textově i formou objektu, což je docela příjemné, protože se jQuery postará o poskládání do URL), ve třetím je přímo tělo funkce pro obsluhu úspěšného obsloužení a čtvrtým je typ dat, který je ze serveru očekáván.
Metoda get()
vrací objekt (typu jqXHR
), který lze využít pro volání metod, jimiž se nastavuje obsluha dalších událostí. Zde se volá always()
, čímž se nastaví obsluha události úplného dokončení požadavku, ať už byl úspěšný či nikoli. V tomto případě se jen nastaví proměnná reqRun
na false
, ale může tam být v podstatě cokoli podle potřeby.
Takto by šlo nastavit i funkci pro obsluhu úspěšného dokončení požadavku – předala by se jako parametr do metody done()
. Funkce pro obsluhu selhání požadavku (ať již selhal z jakéhokoli důvodu) by se nastavila zavoláním fail()
.
Více možností požadavků na server
Uvedený příklad ukazuje jednoduché využití požadavků AJAX. Někdy ale potřebujeme více ovlivnit, jak bude požadavek vypadat a jak přesně proběhne. Pak je lepší si předem připravit objekt a do něj uložit potřebná data. Už i ten předchozí jednoduchý by šel přepsat do této podoby (jen výkonná část, zbytek je stejný):
var req = { url: 'content.php', dataType: 'html' }; $get(req) .done: function(data) { $('#content').html(data); } .always(function() { reqRun = false; });
Zde můžete vidět jak přesun parametrů do samostatného objektu, tak nastavení obslužné funkce pro úspěšný požadavek až po vytvoření objektu požadavku. Úplně stejně by ale šla nastavit do položky success
v objektu.
Přístup s objektem umožňuje ještě podstatně větší flexibilitu. Získáme ji zejména s metodou ajax()
, kterou lze použít i pro jiné typy požadavků než GET. Hodí se to zejména v případech, kdy využíváme striktní přístup CRUD a využívají se tedy čtyři HTTP metody.
Jiné metody než GET a POST nemusí fungovat ve všech prohlížečích, proto se mnohdy využívá zjednodušené řešení, kdy GET slouží pro požadavky ke čtení a POST pro všechny požadavky nějak měnící data.
var req = { method: 'POST', url: 'save.php', dataType: 'json', contentType: 'multipart/form-data', timeout: 3000, data: {...}, success: function() {...}, statusCode: { 404: function() { alert('Obslužný skript nebyl nalezen, kontaktujte správce.'); } } }; $.ajax(req);
Příklad ukazuje část možností parametrizace požadavku a obsluhy souvisejících událostí. Jako HTTP metoda se použije POST, jako datový typ je očekáván JSON (jQuery data zvaliduje a při úspěchu zkonvertuje, při neplatných datech nastane chybová událost), data se odesílají převedená na typ multipart/form-data
a časový limit je 3000 ms.
Do položky data se vloží objekt (je převeden na zmíněný „formulářový“ formát), při úspěchu se volá příslušná obslužná funkce (zde vložená přímo do objektu). Zajímavá je položka statusCode
, která umožňuje reagovat na konkrétní stavové kódy HTTP. Zde se reaguje na kód 404, tedy nenalezení požadovaného objektu. Funkce k obsluze událostí se nastavují do položek objektu.
Zjednodušující metody
Kromě již zmíněné zjednodušující metody get()
jsou tu i další podobné. Například požadavky typu POST lze posílat metodou post()
. K získání dat určitého typu dat jsou to specializovanější metody – konkrétně getJSON()
a getScript()
. Obě fungují jako get()
s nastavením příslušného typu.
Pokud je tím typem „script“ (bez ohledu na to, která metoda se volá), je načtený skript následně spuštěn.
Úplnou lahůdkou je pak metoda load(), která zajišťuje načtení kusu HTML a jeho použití ve stránce (tedy to, co bylo v prvním příkladu). Volá se přímo na objektu v DOM, jehož obsah se má změnit:
$('#content').load('content.php');
Velmi jednoduché, že? Pozor ale na to, že metoda nevkládá přímo to, co se načetlo – místo toho najde v načteném kódu příslušný identifikátor a nahradí jen obsah daného elementu. Není samozřejmě také nijak řešeno opakované zavolání v případě, že požadavek ještě probíhá.
Animace a efekty
To by bylo okolo událostí i požadavků na server zatím vše, i když se k nim ještě později vrátíme. Příští díl bude zaměřen na podporu jQuery pro některé vizuální efekty a animace.