Přidat článek mezi oblíbenéZasílat nové komentáře e-mailem Ajax - XMLHttpRequest

V predchádzajúcom dieli bolo vymenovaných niekoľko možných spôsobov komunikácie medzi klientom a serverom. Dnes sa zameriame na jeden z nich a ukážeme si, ako odosielať požiadavky a spracovať odpovede prostredníctvom objektu XMLHttpRequest.

Spôsobov, ako implementovať komunikáciu klienta so serverom je viac, avšak použitie objektu

XMLHttpRequest

sa s technikou Ajax spája asi najčastejšie. Použitie tohto objektu je v podstate jediné čisté riešenie komunikácie, pri ktorom sa technológia používa presne na to, na čo bola určená.

XMLHttpRequest

umožňuje vytvárať požiadavky s použitím rôznych metód, vrátane metód GET a POST. V dnešnej dobe ho podporujú všetky súčasné prehliadače.

Objekt

XMLHttpRequest

umožňuje prenášať údaje vo formáte XML, vďaka čomu môžeme na strane klienta jednoduchšie spracovávať prijaté údaje. Rovnako je však možné prenášať čistý text, čo sa hodí v prípadoch, v ktorých by bol XML formát kanónom na vrabce. Hoci je

XMLHttpRequest

určený na komunikáciu klienta so serverom, nie vždy je to tá najlepšia voľba. Nedostatkom objektu

XMLHttpRequest

je, že v prehliadači Internet Explorer je možné tento objekt vytvoriť iba s použitím technológie ActiveX. To môže byť problémom, pretože pri vyššom stupni zabezpečenia sa pri vytváraní tohto objektu môže používateľovi zobraziť otravná hláška, prípadne sa nemusí objekt

XMLHttpRequest

vôbec vytvoriť. V prehliadači Internet Explorer 7 už toto obmedzenie neplatí a objekt

XMLHttpRequest

sa dá vytvoriť rovnakým spôsobom ako v ostatných prehliadačoch.

Ďalšou vlastnosťou komunikácie prostredníctvom objektu

XMLHttpRequest

je, že nie je možné komunikovať so serverom z inej domény, než z ktorej bol spustený skript. Toto obmedzenie sa dá obísť nastavením prehliadača, ale z bezpečnostného hľadiska to nie je príliš rozumné. Ak by totiž bola povolená komunikácia so servermi z inej domény, bolo by jednoduché okrem iného napríklad hlasovať za nejakú možnosť v ľubovoľnej ankete, prípadne z Vašej IP adresy vložiť príspevok do nejakej diskusie na inej stránke. Pre komunikáciu so servermi z inej domény je preto lepšie vytvoriť na serveri proxy stránku, ktorá takúto komunikáciu zabezpečí.

Vytvorenie objektu XMLHttpRequest

Pri vytváraní objektu

XMLHttpRequest

sa postupne skúšajú viaceré spôsoby. Uprednostňuje sa vytvorenie objektu

XMLHttpRequest

jeho konštruktorom, ako keby to bol objekt ako každý iný. Až v prípade, že konštruktor nie je k dispozícii, príde na rad vytvorenie tohto objektu pomocou technológie ActiveX. V mnohých ukážkach na webe bolo toto poradie opačné a v podstate na ňom do istej doby ani nezáležalo. Ak bola k dispozícii technológia ActiveX, vytvoril sa

XMLHttpRequest

pomocou nej a až keď sa to nepodarilo, použil sa konštruktor pre

XMLHttpRequest

. Príchodom prehliadača Internet Explorer 7 už na poradí záleží, pretože ten umožňuje vytvoriť

XMLHttpRequest

obidvomi spôsobmi, pričom chceme uprednostniť natívny objekt

XMLHttpRequest

.

function createXhr ()
{
	var xhr = null;

	if (window.XMLHttpRequest)
		xhr = new XMLHttpRequest ();
	else if (window.ActiveXObject)
		try { xhr = new ActiveXObject ("Msxml2.XMLHTTP"); }
		catch (e)
		{
			try { xhr = new ActiveXObject ("Microsoft.XMLHTTP"); }
			catch (e) {}
		}

	return xhr;
}

Možno sa pýtate, prečo sa pokúšame vytvoriť ActiveX objekt

Msxml2.XMLHTTP

a pri neúspechu vyskúšame ActiveX objekt

Microsoft.XMLHTTP

. Je to tým, že objekt

XMLHttpRequest

má viacero implementácií. Pomocou objektu

Microsoft.XMLHTTP

bolo možné vytvoriť objekt na komunikáciu so serverom dávno pred tým, než sa objavil objekt

XMLHttpRequest

v iných prehliadačoch. Neskôr vznikla ďalšia verzia tohto objektu

Msxml2.XMLHTTP

, ktorá sa líši snáď iba pomenovaním.

Vytvorený objekt

XMLHttpRequest

poskytuje niekoľko metód:

abort ():
Ukončí požiadavku.
getAllResponseHeaders ():
Vráti v reťazci zoznam všetkých hlavičiek.
open ("metóda", "url"[, asyncFlag[, "userName"[, "password"]]]):
Priradí požiadavke cieľovú URL, metódu a ďalšie voliteľné parametre.
send (content):
Odošle požiadavku so zadaným obsahom.
setRequestHeader ("label", "value"):
Pridá k požiadavke hlavičku.

Vlastnosti objektu XMLHttpRequest:

onreadystatechange:
Funkcia pre obsluhu udalosti zmeny stavu objektu.
readyState:
Číslo reprezentujúce aktuálny stav objektu: 0 = nenainicializovaný (uninitialized), 1 = nahráva (loading), 2 = nahraný (loaded), 3 = interaktívny (interactive), 4 = dokončený (complete)
responseText:
Reťazec s údajmi, ktoré poslal server.
responseXML:
XML (DOM-kompatibilný objekt) s údajmi, ktoré poslal server.
status:
Návratový kód odpovede, ako napr. 404 pre nenájdenú stránku alebo 200 pre úspech.
statusText:
Text, ktorý dopĺňa návratový kód odpovede.

Odoslanie požiadavky

Z predchádzajúceho výpisu metód objektu

XMLHttpRequest

vidíme, že pri otváraní novej požiadavky môžeme nastaviť, či má byť volanie synchrónne alebo asynchrónne. Predvolená hodnota je

true

, takže bez uvedenia tretieho argumentu metódy

open

bude volanie asynchrónne. Ak by sme nastavili tretí argument na

false

, volanie by bolo synchrónne. To by znamenalo, že hneď po zavolaní metódy

send

by sme mohli pracovať s odpoveďou, ku ktorej by sme sa dostali prostredníctvom vlastností

responseText

alebo

responseXML

. Avšak pri synchrónnom volaní musí klient na odpoveď čakať a počas tohto čakania nemôže nič robiť. Preto je vždy lepšie použiť asynchrónne volanie (okrem veľmi výnimočných prípadov).

Odoslanie požiadavky metódou POST

Najčastejšie sa používajú metódy

open

a

send

. Odoslanie požiadavky metódou POST by vyzeralo nasledovne:

function sendRequest (data, url)
{
	var xhr = createXhr ();

	if (xhr)
	{
		xhr.open ("POST", url);
		xhr.onreadystatechange = function () { if (receiveResponse (xhr)) xhr = null; };
		xhr.setRequestHeader ("Content-Type", "application/x-www-form-urlencoded");
		xhr.send (data);
	}

	return xhr;
}

Pri asynchrónnom volaní nastavíme obslužnú funkciu udalosti

readystatechange

, ktorá sa potom zavolá pri každej zmene stavu požiadavky. Tu by som chcel upozorniť na funkciu, ktorú sme v príklade použili ako obslužnú. Táto funkcia volá ďalšiu funkciu

receiveResponse

, ktorej v argumente posunieme objekt

xhr

. Dôležité je to, že po spracovaní odpovede, keď už viac nebude potrebné pristupovať k objektu

xhr

, vráti funkcia

receiveResponse

hodnotu

true

, aby bolo možné uvoľniť objekt

xhr

z pamäte. V mnohých ukážkach na webe takéto uvoľňovanie pamäte chýba, čo má za následok v niektorých prehliadačoch to, že pri každej požiadavke na server sa obsadí ďalší kus pamäte. Konkrétne ide o tzv. memory leaks v prehliadači Internet Explorer. Táto pamäť sa dá potom uvoľniť jedine reštartom prehliadača.

Pri požiadavkách odosielaných metódou POST musíme ešte nastaviť hlavičku požiadavky

Content-Type

na

application/x-www-form-urlencoded

, aby server vedel, že obsahom je zakódovaný formulár.

Odoslanie požiadavky metódou GET

Odoslanie požiadavky metódou GET je veľmi podobné, ale o niečo jednoduchšie. Keďže odosielané údaje sú zakódované už priamo v URL, netreba ich v metóde send nastavovať. Podobne netreba nastavovať hlavičku:

function sendRequest (data, url)
{
	var xhr = createXhr ();

	if (xhr)
	{
		xhr.open ("GET", url);
		xhr.onreadystatechange = function () { if (receiveResponse (xhr)) xhr = null; };
		xhr.send (null);
	}

	return xhr;
}

Nasledujúcim krokom bude prijatie a spracovanie odpovede nastavenou metódou

receiveResponse

.

Prijatie odpovede

Pri vytváraní požiadavky sme priradili objektu

XMLHttpRequest

obslužnú funkciu, ktorá sa volá pri výskyte udalosti

readystatechange

. Úlohou tejto obslužnej funkcie je spracovať prijatú odpoveď, prípadne ohlásiť chybu. Môže vyzerať nasledovne:

function receiveResponse (xhr)
{
	if (xhr.readyState == 4)
	{
		if (!xhr.status || xhr.status == 200)
			alert (xhr.responseText);
		else
			alert ("Error: " + xhr.statusText);

		return true;
	}
  
	return false;
}

Pri prijatí odpovede sa v prvom rade skontroluje vlastnosť

readyState

. Tá obsahuje kód stavu, v akom sa požiadavka nachádza. V drvivej väčšine prípadov chceme obslúžiť stav s kódom 4, kedy sa dokončilo prijatie odpovede. V komunikácii cez protokol HTTP má každá odpoveď svoj stav, ktorý je vyjadrený číslom vo vlastnosti status. Ak prišla odpoveď v poriadku, bude jej stav označený číslom 200. Iný stav znamená, že pravdepodobne nastala nejaká chyba. Ak spúšťame skript z lokálneho počítača bez použitia webového servera, môžeme pristupovať priamo k súborom na disku. Keďže v takomto prípade nekomunikujeme s webovým serverom, nemusí byť stav odpovede nastavený.

Táto funkcia vráti

true

v prípade, že požiadavku spracovala a objekt

xhr

nebude už viac potrebovať. V opačnom prípade vráti

false

. Ako bolo skôr spomenuté, takéto správanie sme si definovali kvôli správnemu uvoľňovaniu pamäte.

Záver

V tejto časti seriálu sme si ukázali základy práce s objektom

XMLHttpRequest

, ktoré by mali stačiť na vytvorenie jednoduchej komunikácie klienta so serverom. V ďalšej časti si ukážeme, ako by sa dala realizovať ekvivalentná komunikácia prostredníctvom skrytého rámca.

Čím sa líši táto ukážka od ostatných príkladov komunikácie klienta so serverom dostupných na Internete je hlavne to, že sa staráme aj o uvoľňovanie pamäte. Keď nepoužívame takúto komunikáciu intenzívne, nemusíme sa o neuvoľnenú pamäť príliš starať. Pri častej komunikácii však bez uvoľňovania pamäte hrozí kolaps aplikácie, webového prehliadača, prípadne celého systému z dôvodu vyčerpania systémových zdrojov.

loading...
Předmět Autor Datum
Dobré. Potíže s memory leaks mají dost prohlížeče sami o sobě. Třeba u mě je to znatelné už po větší… nový
Flash_Gordon 30.10.2006 22:23
Flash_Gordon
Pri každom odoslaní požiadavky sa vo funkcii sendRequest vytvára nový objekt, ktorý sa zapamätá v no… poslední
los 31.10.2006 09:18
los

Dobré. Potíže s memory leaks mají dost prohlížeče sami o sobě. Třeba u mě je to znatelné už po větším počtu otevřených stránek :-). Musím po čase resetovat prohlížeč, aby mi to běhalo svižněji. Z tohoto důvodu je dost dobré to doplnění o "return false;

Jinak by se dost lidí asi divilo při různém, intenzivním využívání této funkce aplikací, kde se jim pořád ztrácí paměť.

Ale stejně si to ještě vyzkouším, protože při opakovaném použití funkce function sendRequest (data, url) je použito:
var xhr = createXhr (); Od čehož bych očekával, že zruší předchozí zabranou paměť :-/ respektive bych očekával, že objekt xhr nebude v paměti více než 1x.... nebo ano ?

Pri každom odoslaní požiadavky sa vo funkcii sendRequest vytvára nový objekt, ktorý sa zapamätá v novej premennej xhr. Tá sa po dokončení vykonávania funkcie sendRequest nemôže uvoľniť, pretože je použitá v anonymnej funkcii, ktorá obsluhuje udalosť readystatechange. Neuvoľní sa ani pri opustení stránky, pretože V IE vznikne kruhová referencia medzi ActiveX objektom a objektom JavaScriptu, s ktorou má Garbage Collector problém.

Na komunikáciu by sa mohol používať len jeden objekt XMLHttpRequest, ale treba pri tom dodržať nejaký postup (priradiť obslužnú funkciu pre readystatechange až po volaní open): http://keelypavan.blogspot.com/2006/03/reusing-xmlh ttprequest-object-in-ie.html.

Zpět na články Přidat komentář k článku Nahoru

loading...