Könyvhöz tartozó online melléklet

Könyv: Webalkalmazások fejlesztése Ajax segítségével (Kris Hadlock)

Melléklet: Olvasson bele!

1

1. fejezet Az AJAX bemutatása

Köszönet mindenkinek, aki kezébe vette ezt a könyvet! Ebben a kötetben a célunk nem csupán az, hogy megvizsgáljuk az Ajaxot meghatározó technológiákat és azt, hogy ezek kölcsönhatásai miként vezetnek hatékony ügyféloldali együttműködéshez, hanem azt is meg szeretnénk mutatni, hogyan lehet bármilyen Ajax-megfelelő webes alkalmazásban újrahasznosítható, hasznos kódokat írni. Ezek a kódok a vállalkozási szintű alkalmazásokban szükséges méretezhetőség és rugalmasság érdekében teljesen objektumközpontúak lesznek. A könyv fejezetei végigvezetnek bennünket az egyes példákon: hogyan lehet újrahasznosítható Ajax motort készíteni, hogyan lehet az Ajaxszal együttműködő összetevőket létrehozni, valamint – ez a szerző kedvence – miként lehet az Ajax segítségével kiszolgálóoldali nyelvekhez kapcsolódni. Az Ajax különböző támogató technológiákat igényel – az XML-t (Extensible Markup Language, bővíthető jelölőnyelv) és a JSON-t (JavaScript Object Notation, JavaScript objektumjelölés) az adatcseréhez, továbbá a JavaScriptet és a CSS-t (Cascading Style Sheets, többszintű stíluslapok) az adatleképezéshez és -megjelenítéshez –, ezért mielőtt elmerülnénk az Ajax sokrétű világában, ezekre a technológiákra összpontosítunk. Az ügyféloldal és a kiszolgálóoldal együttműködését megismerve megtanuljuk, hogyan lehet az egyes kódokat működő alkalmazásokká gyúrni – végül is ezek annyira szorosan összekapcsolódnak, hogy az Ajaxhoz mindkettő ismeretére szükség van. Olyan, az Ajaxra alkalmazható elterjedt programozási mintákkal is foglalkozunk majd, amelyekkel sokkal gyorsabbá és átláthatóbbá tehetjük a fejlesztést. Ez után elsajátítunk néhány hasznos fogást, amelyekkel biztonságossá tehetjük az Ajax-alkalmazásokat, és közvetlen felhasználói interakciót, valamint üzenetkezelést és más ügyféloldali szolgáltatásokat biztosíthatunk.

Az Ajax mozaikszó az Asynchronous JavaScript and XML (aszinkron JavaScript és XML) kifejezésből ered. Az Ajax központi eleme az XML DOM (Document Object Model, dokumentum-objektummodell) részét képező XMLHTTPRequest objektum. Mivel az XML DOM az Ajax rendkívül fontos része, röviden tekintsük át, hogy lássuk, hogyan kapcsolódik a könyvben tárgyalt témákhoz.

Az XML DOM

Az XML dokumentum-objektummodell az XML dokumentumok elérésének és módosításának szabványos módját határozza meg. A DOM hozzáférést nyújt az XML, illetve az XHTML dokumentumok szerkezetét alkotó elemekhez, ezáltal teljes elérést nyújt a JavaScript számára. A hozzáférést a JavaScript DOM-kezeléssel foglalkozó belső objektumhalmaza teszi lehetővé. A könyvben végig ezt a modellt használjuk majd, mert elengedhetetlen az XMLHTTPRequest (XHR) kérelmek létrehozásakor a kiszolgálóoldalról érkező válaszok feldolgozásához. Ahogy korábban említettük, az XHR az Ajax-modell veleje, ami nélkül a modell nem létezne. Mostanában mindenkit az Ajax-mozaiknak ez a darabja izgat, ugyanis lehetővé teszi, hogy a böngésző frissítése nélkül indítsunk HTTP-kérelmeket.

Az utóbbi időben ugyan megnőtt az Ajax körüli felhajtás, a technológia azonban már elég régóta létezik. A Microsoft eredetileg 1999-ben bocsátotta ki a Windows IE 5-tel együtt, egy JavaScripttel és VBScripttel elérhető ActiveX objektumként, de ma már a Mozilla, a Firefox, a Safari és a Netscape is támogatja egy eredeti JavaScript objektum segítségével, amelyet az Internet Explorer (IE) 7-es kiadása szintén támogat majd. Annak ellenére, hogy ezek a technológiák korábban is léteztek, és számos fejlesztő alkalmazta őket, csak az utóbbi időben váltak igazán népszerűvé. Ez az újonnan szerzett népszerűség jórészt a böngészők által nyújtott támogatásnak köszönhető, mivel a legutóbbi változatok előtt nem sok böngésző rendelkezett a hatékony DHTML-hez, XHTML-hez, CSS-hez és XMLHTTPRequest-ekhez szükséges támogatással. Most már igen jó, több böngészőben, illetve több felületen működő eredményt kaphatunk az ilyen kölcsönhatások létrehozásával. Az említett technológiák jobb támogatásával az Ajax előtérbe került, és a webfejlesztőkre ismét izgalmas korszak köszöntött. Néhány kisebb, független cég rendszeresen áll elő olyan alkalmazásokkal, amelyek hatékony szolgáltatásaikkal és a felhasználói élmény bámulatos bővítésével felveszik a versenyt a munkaasztallal.

Az előnyök mérlegelése

Az Ajax olyan nyelvek hatékony gyűjteménye, amelyek együtt könnyen használható felületeket és ügyféloldali párbeszédet eredményeznek. Sok fejlesztőt azonban annyira izgatottá tesz az Ajax körüli felhajtás, hogy egyszerűen beszúrják a kódot az alkalmazásba, anélkül, hogy előzőleg felmérnék annak előnyeit. Nem minden webalkalmazásban van szükség az Ajaxra, de egy adott alkalmazás számos eleme jobbá tehető az Ajax előnyeinek kiaknázásával. Ebben a könyvben olyan felhasználási mintákat tekintünk át, amelyek a visszajelzéssel, a kiszolgálóoldali űrlapoknak az űrlap elküldése előtti ellenőrzésével és a webalkalmazások egyes elemeit túlzások nélkül feljavítani képes Ajax-megfelelő összetevőkkel foglalkoznak. Az Ajax olyankor is remekül alkalmazható, amikor kiszolgálóoldali kapcsolatot akarunk létrehozni és esetleg adatbázis-műveleteket végezni a böngésző frissítése nélkül. Az Ajax éppen emiatt annyira hatékony, hiszen lehetővé teszi, hogy adatcserét folytassunk a kiszolgálóval, HTTP-állapotkódokat fogadjunk, adatbázisba mentsünk, illetve meghatározzuk, hogy mi jelenjen meg a felhasználó számára, anélkül, hogy egyszer is frissíteni kellene az oldalt. Az asztali alkalmazásokhoz hasonlóan ez a kérelem-válasz körforgás folyamatosan fennállhat, az Ajaxszal együttműködő webalkalmazások azonban a Weben találhatók, tehát bárki, aki internetkapcsolattal rendelkezik, elérheti azokat, és nem kell semmit letöltenie vagy szállítási költséget fizetnie nagy, tarka dobozokért. Az Internet az új munkaasztal – a szoftver nagyszabású változásának küszöbén állunk, amelyben az igény szerint lehívható információ úttörőiként tevékeny szerepet vállalhatunk.

Az Ajax értékes kapcsolatot teremthet a felület és a kiszolgálóoldali logika között, ami lehetővé teszi, hogy a kiszolgálóoldal nagy teljesítményű és hatékony legyen, miközben egyszerű, könnyen használható felülettel rendelkezik, amely igény szerinti visszacsatolást nyújt a felhasználóknak. A kiszolgálóoldali nyelvekkel történő adatcsere, illetve az adatbázisban tárolás lehetőségét is biztosítja, anélkül, hogy a felhasználó és az alkalmazás közötti kapcsolat megszakadna, ahogy a hagyományos alkalmazásokban a böngészőablak frissítésekor történik. A könyv elolvasása után minden olyan információ rendelkezésünkre áll majd, ami a tökéletesen működő Ajax-alkalmazások készítéséhez szükséges.

 

2. fejezet A kérelem

Most, hogy megismertük az Ajax hátterét, és röviden áttekintettük, hogy mit szeretnénk elérni a példaprojektben, felkészültünk a kérelem összeállítására. Ez a fejezet a kérelem belső működését mutatja be, és nem csupán a kérelemobjektum létrehozásának módját ismerteti, hanem a különböző kérelemmodellek megközelítését is megérteti.

Az XMLHttpRequest részletesen

Az XHR (XMLHttpRequest) objektum az Ajax-motor szíve. Ez az objektum teszi lehetővé, hogy az oldal háttérkérelemként kapjon adatokat a kiszolgálótól (a GET eljárás segítségével), illetve küldjön adatokat a kiszolgálónak (a POST eljárás segítségével), ami azt jelenti, hogy a folyamat során nem frissíti a böngészőt. Ahogy azt az 1. fejezetben kifejtettük, az Ajaxot övező felhajtást ez az objektum okozza, továbbá az, hogy az általa létrehozott modell természetesebb, mint a szabványos HTTP- (Hypertext Transfer Protocol, hiperszöveg-átviteli protokoll) kérelem. Ez azért van így, mert a változtatások igény szerint történnek, amikor a felhasználó végrehajtja azokat, ezáltal a webalkalmazás inkább asztali alkalmazás hatását kelti. Az XHR használatakor nem kell a kiszolgálóra várni, hogy minden kérelemre új oldallal válaszoljon, és lehetővé válik, hogy a felhasználók továbbra is kapcsolatban maradjanak az oldallal úgy, hogy a kérelmek küldése a háttérben folyik. Ez kulcsfontosságú a közvetlen felhasználói élmény megőrzéséhez: az a jó, ha a felhasználóknak egyáltalán nem kell tudniuk a folyamatról, ehelyett a szolgáltatást használó aktuális feladatra összpontosíthatnak. Az XHR igénykiszolgáló (on-demand) jellege az olyan webalkalmazásoknál rendkívül hasznos, ahol a felhasználók feladatokat próbálnak megoldani, mert a szabványos HTTP-kérelem inkább a bemutató típusú webhelyeknél alkalmazható.

A háttérben történő adatkezeléstől eltekintve az XHR objektum GET és POST eljárása ugyanúgy működik, mint egy hagyományos HTTP-kérelemnél. A POST és a GET eljárás alkalmazásával egyaránt adatkérelmet küldhetünk a kiszolgálónak, amelyre valamilyen szabványos formátumban kapunk választ. A válaszok leggyakrabban XML, JSON és szöveges formátumban érkeznek. A 3. fejezetben az összes formátumot részletesen áttekintjük. A POST kifejezetten 512 bájtnál nagyobb adatok küldésénél hasznos (ezt a méretet a GET eljárás nem képes kezelni). A válasz fogadása után a DOM vagy a DHTML – amely az XHTML, a JavaScript és a CSS keveréke – segítségével tölthetjük be a kiszolgálótól származó új adatokat az alkalmazásba.

Minden Ajax-kérelem egy ügyféloldali művelettel indul, amelyet általában egy JavaScript-kód kezel. A JavaScript létrehozza az XHR objektumot, és HTTP-kérelmet küld a kiszolgálónak. Ez után sokféle lépés következhet. Vessünk egy pillantást a három leggyakoribb kérelemmodellre és azok folyamataira.

Szabványos XHR

Ha egy Ajax-kérelmet lebontunk a puszta működés szintjére, csupán ez marad. Ebben az esetben az XHR objektum a GET eljárás segítségével egy azonos tartományban található állandó XML, JSON vagy szövegfájlt kér, amelyet azután a kiszolgáló visszaküld, hogy a kérelmet indító ügyféloldali kód kezelje. A 2.1. ábrán a szabványos Ajax-modell folyamatát láthatjuk.

2.1. ábra

Ez a kérelem az Ajax kérelem-válasz modelljének legegyszerűbb formája, amely mindössze egy azonos tarto-mányban található XML, JSON vagy szövegfájlt igényel

Ez a kérelemfajta olyankor lehet hasznos, amikor egy webhez értő ügyfél vagy egy fejlesztő frissíti a kért fájlt a kiszolgálón, ami ritkán fordul elő, különösen a nagyméretű alkalmazásoknál. Ha ez a modell nem felel meg az igényeinknek, a következő megközelítésben már szerepel az, ami ebből a modellből leginkább hiányzik: az adatbázis.

Adatbázis-megfelelő XHR

Az adatbázis-megfelelő XHR-ek létrehozásának elsajátítása olyan, mint amikor először végzünk adatbázis-műveletet. Az új lehetőségek egész tárházát nyitja meg előttünk, és nem is annyira bonyolult, mint képzelnénk; az adatbázisképes Ajaxszal elérhető összetett szolgáltatásrendszert tekintve gyerekjáték. A modell használatához először egy kiszolgálóoldali nyelvhez kell kérelmet indítani. A kiszolgálóoldali nyelv egyedi, meghatározott adatbázis-műveletek kezelése céljából írt eljárásokkal kérdezi le az adatbázist a kérelemnek megfelelően. Miután a kiszolgálóoldali nyelven írt kód megkapja az adatokat, visszaküldheti az XHR-nek, amely eredetileg az ügyféloldali kód által kezelt XML-ként, JSON-ként vagy szövegként kérte azokat. Ez a kérelem lehetővé teszi, hogy a felhasználók az általuk indított kérelmeknek megfelelő, egyedi adatokat kapjanak. A 2.2. ábrát tanulmányozva jobban megérthetjük az adatbázis-megfelelő XHR folyamatát.

2.2 ábra

Az adatbázis-megfelelő XHR a lehetőségek egész tárházát nyitja meg előttünk, és magasabb szintre emeli Ajax-alkalmazásainkat

Ez a kérelemmodell ugyan jóval hatékonyabb, mint a szabványos kérelem, mégis lehet, hogy ennél is pontosabb szabályozhatóságot szeretnénk. A következő modell lehetővé teszi, hogy adatokat küldjünk az adatbázisnak, és a kérelem alapján kapjunk vissza adatot, vagy egyszerűen egy logikai értéket kapjunk, ha az adatbázisba történő beillesztés (INSERT) sikeres volt – és mindezt az oldal frissítése nélkül.

Adatok küldése az adatbázis-megfelelő XHR-eknek

Ha adatokat akarunk küldeni egy adatbázisba, először egy XHR GET vagy POST eljárást kell küldeni egy kiszolgálóoldali nyelvű kódnak, illetve motornak. Miután a kiszolgáló megkapja a kérelmet, elemzi az XHR által küldött XML-t vagy egyszerű kulcs-érték párt, majd eszerint frissíti az adatbázist. Ez a kérelemmodell felhasználói beavatkozás nyomán frissíti az adatbázist, a böngészőoldal újratöltése nélkül. Ezzel a módszerrel remekül visszaadható az asztali alkalmazásokban szereplő „Mentés” gomb. A példában elektronikus levelek adatbázisba mentésére használjuk majd ezt a modellt, így a felhasználók később lehívhatják a leveleket. A 2.3. ábrán ennek a kérelemtípusnak a folyamatát láthatjuk, az esetleges válaszadatokkal kiegészítve, amelyeket majd a 2. fejezetben tárgyalunk.

2.3. ábra

Az adatbázis-megfelelő XHR POST segítségével az XHR-t teljes adatbázis-eléréssel ötvözhetjük

A fejezetben említett kérelemmodellek közül az adatbázis-megfelelő XHR-eknek történő adatküldés a leghatékonyabb. Lényegében teljes adatbázis-vezérlést biztosít az XHR-en keresztül. Sok különböző helyzet létezik, amikor érdemes az adatokat XHR-rel elküldeni a kiszolgálónak. Hasznos lehet például, ha egy jelszó kiszolgálóra küldésével, majd annak az adatbázis-lekérdezés előtti hitelesítésével védjük az XHR-t. Az is lehet, hogy rekordokat szeretnénk frissíteni vagy beszúrni az adatbázisba, vagy a kérelem alapján rekordokat akarunk kijelölni.

Az Ajaxszal folytatott kiszolgálóoldali párbeszéd lehetővé teszi az adatbázis igény szerinti frissítését, ugyanúgy, ahogy az asztali alkalmazások mentik a munkafolyamatot. A kérelmek kiszolgálóoldalát annyira bőven lehet tárgyalni, hogy az V. részben egy teljes fejezetet szentelünk neki. Mielőtt azonban elmélyednénk az összetett kódban, fontos, hogy biztos ismeretekkel rendelkezzünk az objektumokról és azok képességeiről.

Az objektum létrehozása

Az XHR és a különböző kérelemmodellek bővebb ismeretében már összpontosíthatunk az objektum létrehozására. A kérelemobjektum létrehozása rendkívül egyszerű, ahhoz képest, hogy mennyire hatékony egy projektben alkalmazva.

A kérelemobjektum létrehozásához ellenőrizni kell, hogy a böngésző az XHR vagy az ActiveX objektumot használja. A két objektumot elsősorban az különbözteti meg egymástól, hogy melyik böngésző használja. Az Internet Explorer (IE) 5-ös és későbbi változatai az ActiveX objektumot, míg a Mozilla, a Firefox, a Netscape, az Opera és a Safari az eredeti JavaScript XHR objektumot alkalmazzák. A másik különbség az egyes objektumok létrehozásában rejlik: az IE-nél az objektum nevét paraméterként kell átadni az ActiveX konstruktornak, míg a többi böngészőben rendelkezésre áll az eredeti JavaScript objektum, amelyet csupán példányosítani kell:

function makeRequest(url)

{

if(window.XMLHttpRequest)

{

request = new XMLHttpRequest();

}

else if(window.ActiveXObject)

{

request = new ActiveXObject("Msxml2.XMLHTTP");

}

 

sendRequest(url);

}

Ahogy azt a fenti példakód mutatja, az objektum létrehozása tényleg nagyon egyszerű feladat. Létrehozunk egy makeRequest nevű tagfüggvényt, amely – mint az sejthető – a kérelem indítását kezeli, valamint létrehoz egy az XHR objektum meglétét ellenőrző feltételt, amellyel megfejti, hogy a böngésző milyen objektumot használ. Ha ez az objektum nem áll rendelkezésre, az ActiveXObject-et keressük. Miután meghatároztuk a helyes objektumtípust az adott böngésző számára, példányosítjuk a megfelelő objektumot, és létrehozzuk a kérelemobjektumot. Ezzel az objektummal ezután el lehet érni az XHR objektum összes rendelkezésre álló tulajdonságát és tagfüggvényét, amelyeket a 2.1. és a 2.2 táblázat sorol fel.

2.1 táblázat Az XHR tulajdonságai és azok meghatározása

Tulajdonság Meghatározás

onreadystatechange ‑Eseménykezelő, amely a kérelemobjektum állapotának változásakor indul el.

readyState ‑Az objektum aktuális állapotát jelző számértékeket ad vissza. Az értékek felsorolása a 2.3. táblázatban látható.

responseText A kiszolgálótól érkező válasz karakterlánc-változata.

responseXML ‑A kiszolgálótól érkező válasz DOM-megfelelő dokumentumobjektuma.

status A kiszolgálótól érkező válasz állapotkódja.

statusText Karakterláncként visszaadott állapotüzenet.

2.2 táblázat Az XHR tagfüggvényei és azok meghatározása

Tagfüggvény Meghatározás

Abort() Visszavonja az aktuális HTTP-kérelmet.

getAllResponseHeaders() Kigyűjti az összes HTTP-fejléc értékét.

getResponseHeader("címke") ‑Kigyűjti az összes meghatározott HTTP-fejléc értékét a választörzsből.

Open("tagfüggvény", Meghatároz egy MSXML2.XMLHTTP vagy "URL"[, asyncFlag egy Microsoft.XMLHTTP kérelmet, majd beállítja [, "felhasználónév"[, a kérelemhez tartozó tagfüggvényt, URL-t és "jelszó"]]]) a hitelesítési információkat.

Send(content) ‑HTTP-kérelmet küld a kiszolgálónak, majd fogadja a választ.

SetRequestHeader("címke", A címke alapján meghatározza a HTTP-fejléc értékét."érték")

Úgy tűnhet, hogy a két táblázat nem sok lehetőséget tartalmaz, de a későbbi fejezetekben kiderül, hogy ezek kiszolgálóoldali kóddal, adatbázissal és dinamikus ügyféloldallal együtt alkalmazva rendkívül hatékonyak.

Aszinkron adatátvitel

Ha valaki nem járatos az adatátvitelben, és nem pontosan érti, hogy valójában mit jelent az aszinkron adatátvitel, nem kell aggódnia: valószínűleg nem tud arról, hogy már tisztában van a fogalommal, és valószínűleg alkalmazta is más programok fejlesztésekor. A programozási nyelvekben ez a műveletfajta a leggyakoribb, és az XHR, illetve ezáltal minden vállalati Ajax-alkalmazás fontos része. Ez a rész eloszlatja az aszinkron adatátvitelt övező titokzatosságot, mielőtt még elmerülnénk az objektumközpontú Ajax-motor kódolásában.

Az aszinkron adatátvitel olyan kétirányú párbeszéd, ami időeltolódással történik, lehetővé téve, hogy az adatok a maguk idejében érkezzenek, amikor hozzáférhetők. Más szóval megtehetjük, hogy kérelmet indítunk a kiszolgálóhoz, folytatjuk a többi adat feldolgozását, majd fogadjuk a válaszokat, amikor a kiszolgáló elérhető. Ezáltal a webalkalmazás rendkívül rugalmassá válik. Az Ajax-motorban az XHR kérelem–válasz modellje alaphelyzetben aszinkron jellegű. Ez azt jelenti, hogy a kérelem–válasz adatok nem előre meghatározottak, illetve rendszeres időközönként továbbítódnak. Ha például HTTP-kérelmet küldünk a kiszolgálónak, folytathatjuk a többi ügyféloldali művelet feldolgozását, miközben a háttérben a válaszra várunk. Ez mind történhet azalatt, amíg a felhasználó más feladatokon dolgozik, vagy más műveleteket végez, és egyáltalán nincs tudomása a háttérben folyó adatfeldolgozásról. Vagyis hívásokat indíthatunk egy kiszolgálóoldali nyelvű programhoz, hogy adatokat keressen az adatbázisban, és azokat XML, JSON vagy szöveges formátumban adja vissza. Adatokat is küldhetünk a kiszolgálóoldali nyelvnek, hogy az adatbázisban tárolja azokat, vagy egy statikus XML, JSON, illetve szövegfájl betöltésével dinamikusan feltölthetjük a webhely oldalait anélkül, hogy frissítenénk az oldalt, vagy megszakítanánk a felhasználói párbeszédet az ügyféloldalon.

Ennek a kérelemnek a feldolgozásához először két XHR-tagfüggvényt kell meghívni: az open-t és a send-et. Az XHR objektum open tagfüggvénye három paramétert fogad. Az első egy karakterlánc, amely azt mutatja, hogy milyen eljárással küldjük a kérelmet. Ez az eljárásérték GET, POST vagy PUT lehet. A második paraméter az URL, amelyet karakterlánc formájában kérünk – ez lehet XML, JSON, szöveg, vagy ezen formátumok bármelyikét visszaadó kiszolgálóoldali nyelv. Az utolsó paraméter – számunkra most ez a legfontosabb – olyan logikai érték, amely aszinkron átvitelnél alapértelmezésben true (igaz), szinkron átvitelnél pedig false (hamis). A send tagfüggvény az open után következik, és valójában ez küldi el a HTTP-kérelmet, és fogadja az általunk meghatározott formátumú választ. Egy karakterlánc paramétert vár, ami lehet XML vagy egy POST-ként küldött egyszerű kulcs–érték pár. Lássunk egy egyszerű példát arról, hogy miként használjuk az open és a send tagfüggvényt egy egyszerű Ajax-kérelemben:

request.open("tagfüggvény", "URL", true);

request.send(null);

Előfordulhat, hogy az aszinkron adatátvitel nagyszabású rendszerekben nehézkesen kezelhetőnek bizonyul, mégis sokkal jobban méretezhető és használható, mint a szinkron adatátvitel. Ahhoz, hogy különböző képességekkel és tapasztalatokkal rendelkező, összetett felhasználói kört lehessen kiszolgálni, a fejlesztőknek olyan többrétű alkalmazásokat kell létrehozniuk, amelyek sokféle feladatot tudnak kezelni. Az aszinkron párbeszéd egyszerre több feladat végrehajtását és hatékonyabb munkavégzést tesz lehetővé az ilyen felhasználói körnek, megkímélve őket attól a nyűgtől, hogy a kiszolgáló válaszaira kelljen várniuk. A szinkron műveletek megvárják a kérelemre érkező választ, mielőtt újabb kérelmet lehetne küldeni. Egy nagyszabású webalkalmazásban egy ilyen művelet miatt könnyen leállhat az oldal, mialatt a kiszolgáló egyenként dolgozza fel a sorban álló kérelmeket. Az alkalmazás végül használhatatlanná válna, és a felhasználók valószínűleg elpártolnának tőle.

A készenléti állapot

Az XHR objektum létrehozása és a kérelem elindítása után tudnunk kell, hogy a válasz megérkezett-e. Ilyenkor használjuk az onreadystatechange eseménykezelőt. Az onreadystatechange eseménykezelő akkor indul el, amikor a kérelemobjektum állapota megváltozik, és lehetővé teszi, hogy visszahívó eljárást indítsunk. A visszahívó eljárás elindulása után nekünk kell kezelni a választ. A 2.1. kódszövegben bemutatott, onResponse nevű egyedi visszahívó eljárást a 3. fejezetben tárgyaljuk, ahol az Ajax-válaszok összes elemével foglalkozunk.

2.1. kódszöveg Kérelem küldése

function sendRequest(url)

{

request.onreadystatechange = onResponse;

request.open("GET", url, true);

request.send(null);

}

A 2.2. kódszöveg egy checkReadyState nevű egyedi eljárás, amely ellenőrzi az XHR objektum készenléti állapotát, és az egyes állapotokat külön ágakban kezeli, az adott állapotnak megfelelő szám szerint. Ezt az egyedi eljárást az onResponse tagfüggvény hívja meg, hogy meghatározza az XHR objektum készenléti állapotát, mielőtt elvégezné a válaszobjektum feldolgozását.

2.2. kódszöveg A readyState értékének meghatározása

function checkReadyState(obj, id)

{

switch(obj.readyState)

{

case 0:

document.getElementById(id).innerHTML = "Kérelem küldése...";

break;

case 1:

document.getElementById(id).innerHTML = "Válasz betöltése...";

break;

case 2:

document.getElementById(id).innerHTML = "Válasz betöltve...";

break;

case 3:

document.getElementById(id).innerHTML = "Válasz kész...";

break;

case 4:

document.getElementById(id).innerHTML = "";

return (obj.status == 200);

break;

default:

document.getElementById(id).innerHTML = "Váratlan hiba.";

}}

Megfigyelhetjük, hogy a fenti eljárásban két paraméter szerepel. Az első paraméter neve obj – ez a kérelmet küldő XHR objektum, amely most a kiszolgálótól érkező válasz readyState állapotának ellenőrzésére szolgál. A readyState-re vonatkozó különböző visszaadott értékeket és azok magyarázatát a 2.3. táblázatban olvashatjuk.

2.3. táblázat A readyState-értékek jelentése és meghatározása

readyState-érték Jelentés Meghatározás

0 Nincs kezdőérték Az objektumban még nem szerepelnek adatok.

1 Töltés Az objektum tölti az adatokat.

2 Töltés kész Az objektum befejezte az adatok töltését.

3 Interaktív ‑A felhasználó kapcsolatot létesíthet az objektummal, annak ellenére, hogy a töltés nem fejeződött be teljesen.

4 Kész Az objektum teljes mértékben működésre kész.

A második, id nevű paraméter az ügyféloldali XHTML-ben található HTML elemek azonosítója. Ezt az azonosítót a JavaScript document.getElementById tagfüggvénye keresi meg, amellyel a DOM-ot éppen használó oldalon azonosító alapján lehet megtalálni a meghatározott elemet. Amikor ez az elem megvan, az innerHTML tulajdonságába egy testreszabott üzenet kerül, amelyet az adott készenléti állapothoz kapcsolva akarunk megjeleníteni. Ez kitűnő módszer arra, hogy visszajelzést adjunk a felhasználónak a kérelmek állapotáról. A 2.2. kódszövegben látott módon olyan szöveges üzenetet adunk meg, amely lényegében az egyes állapotokra jellemző betöltési üzenetet jelenít meg, hivatkozási rendszert biztosítva a felhasználó számára. Ha a readyState eléri a 4-es értéket, az azt jelenti, hogy befejeződött a töltés, és ezután a checkReadyState eljárás megmondja, hogy a válasz állapota egyenlő-e 200-zal. A 200-as HTTP-állapot azt jelenti, hogy a kérelem sikeres volt, és készen áll a feldolgozásra. Ez egyike annak a sok HTTP-állapotkódnak, amit kaphatunk, és amit az Ajax-motornak helyesen kell kezelnie. A következő részben további állapotkódokat ismerhetünk meg, továbbá a HTTP-állapotkódok és -fejlécek leggyakoribb felhasználási módjait bemutató példákat találunk.

HTTP-állapotkódok és -fejlécek

Az Ajax-objektum kérelemállapota megegyezik a kért fájl HTTP-állapotával. A HTTP-állapotkódok a kiszolgáló válaszát jelölik, ami a kért fájl állapotát tükrözi. A HTTP-kérelem és az XHR számára elérhető állapotkódok öt csoportba sorolhatók:

Tájékoztató: 1xx Ügyfélhiba: 4xx

Sikeres: 2xx Kiszolgálóhiba: 5xx

Átirányítás: 3xx

A Weben keresztül kapott állapotkódokat számok jelölik – gondoljunk arra, amikor meg szeretnénk látogatni egy webhelyet, és 404-es hibát kapunk. Ez nem tetszőleges szám, hanem a fájlállapot megfelelője, ami ebben az esetben „A fájl nem található” válasz. A kiszolgálónak – és ezáltal a kérelmet indító Ajax-motornak is – minden állapotkódot megfelelően kell kezelnie. Az XHR objektummal történő kérelemindításkor a választ fogadó parancsfájlnak kell feldolgoznia ezeket az állapotkódokat. Ez azt jelenti, hogy a fejlesztő felelős azért, hogy a válasz alapján visszajelzést adjon a felhasználónak, amit valóban meg kell tennie, ha jól használható webalkalmazást akar készíteni. Sikeres válasz esetén az új adat jellemzően XHTML-ként képeződik le az ügyféloldalon; ellenkező esetben megjeleníthető valamilyen üzenet, amely értesíti a felhasználót, hogy a művelet sikertelen volt, illetve megadja a hiba jellegét. A hibakezelés kódolása nem a legizgalmasabb dolog a világon, de elengedhetetlen ahhoz, hogy használható alkalmazásokat készítsünk, ráadásul olyan gyakorlatra tehetünk szert, amit más kódolási körülmények között nem tudnánk megszerezni. A hibakezeléssel a II. részben ismerkedünk meg részletesebben, ahol egyedi objektumokat hozunk létre az összes lehetséges állapotkód kezelésére, valamint hasznos üzeneteket adunk válaszként a hibakereséshez, valamint a felhasználók tájékoztatása céljából. Ha valaki többet akar megtudni a HTTP-állapotkódokról, a W3C (World Wide Web Consortium) webhelyén, a http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html címen megtalálja a meghatározások teljes listáját.

Az XHR objektum HTTP-fejléceket is fogadhat, illetve beállíthat a kiszolgálón. A fejlécek segítségével meghatározott adatokat gyűjthetünk egy kért fájlról, vagy információkat kaphatunk bizonyos kiszolgálótulajdonságokról. Ezek az adatok például akkor lehetnek hasznosak, amikor a tartalom típusát meghatározó content-type fejléc alapján döntjük el, hogy miként elemezzünk egy kért fájlt. Ha a tartalom típusa mondjuk text/XML (szöveg/XML), akkor tudjuk, hogy az XML DOM alkalmazásával elemezhetjük, és megfelelő tagfüggvényeket készíthetünk a különböző tartalomtípusok kezelésére. Sok más döntést is lehet hozni a HTTP-fejlécek alapján.

Az XHR objektumban három eredeti fejlécfüggvény található: a setRequestHeader, a getResponseHeader és a getAllResponseHeaders. A setRequestHeader tagfüggvény lehetővé teszi, hogy a fejléc címkével történő azonosításával és valamilyen érték átadásával beállítsuk a fejléc értékét. A függvény utasításformája a következő:

request.setRequestHeader("címke", "érték");

A kérelem fejlécének beállításával az adott kérelem során hozzáadjuk, töröljük, felülírjuk vagy lecseréljük a HTTP-kérelem fejlécének alapértelmezett értékét. A nyelvtanilag helytelen fejlécek nem továbbítódnak, hanem hiba keletkezik, ezért a fejléc beállítása sikertelen lesz.

A fejlécek beállításán túl az XHR azt is lehetővé teszi, hogy a válasz közben lekérjük a fejléceket. Erre a célra két tagfüggvény használható: a getResponseHeader és a getAllResponseHeaders. A getResponseHeader tagfüggvény a fejléc címkéjét alkalmazza paraméterként, amelynek segítségével meghatározott adatokat szerzünk az adott fejlécből. Íme a két tagfüggvény egy-egy példája:

request.getResponseHeader("címke");

request.getAllResponseHeaders();

A getAllResponseHeaders tagfüggvény a válasz összes fejlécét visszaadja, amelyek a választ küldő kiszolgálótól függően változnak. A 2.4. ábrán szereplő példában egy XML fájl összes fejléce látható, amelyek azon a Windowst futtató kiszolgálón érhetők el, ahol a szerző webhelye jelenleg működik.

2.4. ábra

A getAllResponseHeaders tagfüggvénnyel lekérhető összes HTTP-fejléc

A fentiek csupán rövid bepillantást adtak abba, hogy milyen hasznosak lehetnek a fejlécek a webalkalmazásokban. Később több száz felhasználási módot találunk majd, de ezek nem tartoznak a könyv témájához. A HTTP-fejlécekről a W3C webhelyén, a http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html címen tájékozódhatunk bővebben, ahol a teljes felsorolásuk megtalálható.

 

3. fejezet A válasz

A 2. fejezetben a készenléti állapot és az állapotkódok tárgyalásakor szó esett a válaszról. Ebben a fejezetben a kérelem állapotánál tovább megyünk, és két olyan adatcsere-formátumra összpontosítunk, amelyekben a válaszokat fogadhatjuk. Az Ajax-válaszok különböző formátumokban érkezhetnek: a leggyakoribb a JSON, a legszélesebb körben elfogadott pedig az XML. Mindkettő hasznos lehet, attól függően, hogy milyen eredményt akarunk elérni. A jövőbeni kezelés szempontjából azonban érdemes az alkalmazáson belül egyetlen formátumnál maradni, különösen akkor, ha nagy léptékű alkalmazást készítünk. Ha például valamilyen helyzetben az XML-t használjuk válaszformátumként, sokkal egyszerűbb, ha továbbra is erre a formátumra számíthatunk az összes többi kérelem indításakor. Ez alkalmazásonként változhat, de amennyiben lehetséges, kövessük ezt az elvet. A választott megoldás méretezhetőségét is érdemes szem előtt tartani, különösen ha olyan bővíthető alkalmazás létrehozását tervezzük, amelyben exponenciális növekedésre számítunk. Kezdetnek tanulmányozzuk az XML-t, annak nyelvtanát, az elemzés módját, illetve hogy miként használjuk majd a következő alkalmazásunkban.

XML

Az XML-t (Extensible Markup Language, bővíthető jelölőnyelv) szívesen választják XHR-ként, egyszerűen azért, mert olyan szabványos közvetítő nyelv, amelyet minden programozási nyelv képes használni. Ezen kívül a kiszolgáló- és az ügyféloldalon egyaránt támogatott, emiatt egyben a legrugalmasabb megoldás is. Az XML lényegében egy olyan egyedi címke alapú szerkezet, amelyet a fejlesztő határoz meg. Az XML címkéi hasonlítanak a HTML címkéihez, azzal az eltéréssel, hogy a HTML előre meghatározott címkékkel ábrázolja a szerkezetet, például fejléc, törzs, táblázatok, és így tovább. Lássuk a HTML táblázatok egy rendkívül egyszerű példáját, amelyet könnyen lehetne XHTML-lé alakítani, illetve XHTML-ként alkalmazni:

<table><tr><td></td></tr></table>

Az XML ügyféloldal és kiszolgálóoldal között történő átadásával a különböző nyelvek egyszerűen kommunikálhatnak egymással. Rendkívül előnyös, hogy a kiszolgáló- és az ügyféloldal között létezik ilyen közös nyelv. Lehetővé teszi, hogy közvetlen kapcsolatot létesítsünk a grafikus felhasználói felület és egy kiszolgálóoldali nyelv, majd kívánság szerint egy adatbázis között. A grafikus felület és az ügyféloldal közötti XML-lel megvalósított párbeszéd lehetővé teszi a két alkalmazásréteg teljes különválását. A grafikus felület és a kiszolgálóoldali logika elkülönítése rendkívül fontos, mert ezáltal teljesen önálló alkalmazást kapunk, amelyben a grafikus felhasználói felület fejlesztői dolgozhatnak az ügyféloldalon, míg a kiszolgálóoldali fejlesztők dolgozhatnak a kiszolgálóoldalon. Ez magától értetődőnek tűnhet, de sok vállalatnál hiányzik ez a szemlélet, amely az alkalmazás bizonyos részeit különválasztja a könnyebb kezelhetőség érdekében, és lehetővé teszi, hogy a csoportok, illetve az egyes fejlesztők a jobbításra szoruló rétegre összpontosítsanak. Ez a megközelítés nem csupán a fejlesztőcsapatoknak rendkívül előnyös, hanem minden olyan önálló fejlesztőnek fontos, aki az alkalmazás összes elemén dolgozik. Ezzel a szerkezettel az egyes fejlesztők az alkalmazás bizonyos rétegeire összpontosíthatnak, anélkül, hogy érintenék a szomszédos rétegeket vagy módosítaniuk kellene azokat.

Az XML formázása egyszerű, de a megoldások tervezésekor figyelembe kell venni néhány fontos alapelvet. Képzeljük el, hogy az e-mailek adatait olyan szerkezetté kell formálni, amely egy Ajax motoron keresztül lekérhető, és ügyféloldali JavaScript objektumokkal megjeleníthető. A könyvben szereplő példához éppen ilyen szerkezetet készítünk majd, amelynek tervezésekor érdemes szem előtt tartani, hogy az alkalmazásban esetleg több objektumban, illetve helyen használjuk majd, ezért a lehető legmagasabb elvonatkoztatási szintre van szükség. Először a szerkezetet alkotó fő elemeket határozzuk meg.

Elemek

Az XML elemeknek nevezett egyedi címkékből áll, amelyek meghatározása a webalkalmazások tervezési szakaszában történik. Az alkalmazásban használt bármilyen nevet, értéket vagy adattípust jelölhetnek. Az XML-szerkezetek létrehozásakor mi magunk vagyunk az alkalmazás tervezői, mi döntjük el, hogy milyen adatokra van szükségünk bizonyos egységek képernyőn való megjelenítéséhez, vagy hogy egy adott felhasználói művelet milyen választ eredményezzen.

Fontos, hogy a szerkezetek elvonatkoztatási szintje a lehető legmagasabb maradjon, azáltal, hogy az elemeket nem a célalkalmazástól függően nevezzük el, de erre gyakran nincs lehetőség. Ilyen esetekben nem szerencsés, ha külön időt szánunk arra, hogy az XML-szerkezet elvont legyen, mert lehet, hogy nincs is szükség az XML-adatok újrahasznosítására az alkalmazás különböző részein. Mindamellett az e-mailes XML-mintapéldában lehetséges az elvonatkoztatás, és az alkalmazás más területein végzünk is újrahasznosítást.

Az alábbi XML-formátum használható, de nem kifejezetten bővíthető, illetve újrahasznosítható megoldás:

<categories>

<From/>

<Subject/>

<Date/>

</categories>

 

Ahhoz, hogy az alábbi kategóriák elvontak maradjanak, az elemek nevét category-ra változtatjuk:

3.1. kódszöveg Elvont kategórialista (.xml)

<categories>

<category>From</category>

<category>Subject</category>

<category>Date</category>

</categories>

Ez a lehetőség olyan rugalmasságot biztosít, ami megkönnyíti a további kategóriák hozzáadását. Az utóbbi megoldás számos okból méretezhetőbb; az egyik fontos, megjegyzendő szempont az, hogy az XML-adatok szerkezetének megváltoztatása nélkül adhatunk a listához új kategóriákat. Ezért olyan rugalmas és jobban bővíthető ez a megoldás, mint az előző példáé. Ezen felül, ha objektumokat hozunk létre az adatok megjelenítéséhez, az új elemek kezeléséhez nem kell további elemző és megjelenítő kódot írni. Ezért fontos, hogy olyan elvont szerkezetekkel építsük fel a megoldást, amelyek méretezhetők és könnyen átültethetők más alkalmazásokba vagy objektumokba. Képzeljük el például, hogy kétféleképpen kell megjeleníteni ugyanazt a kategórialistát, mondjuk adatrácsban és e-mail előnézetben. Mindkét objektumnál használhatjuk ugyanazt az elemhalmazt, ami kiküszöböli az alkalmazás kódjában fellelhető ismétlődéseket.

Igaz, hogy az XML-t elemek alkotják, mégsem lehet bármit megvalósítani kizárólag elemek alkalmazásával. Tekintsünk át a jellemzőket, és hogy a segítségükkel miként lehet további információkat fűzni az XML-adatokhoz.

Jellemzők

Az XML-jellemzők olyan kiegészítő tulajdonságok, amelyeket az elemekhez adva további, a szerkezetre vonatkozó információkat adhatunk meg. Vegyük az e-mailes példa egy e-mail elemét. Az elektronikus levelek számos jellemzővel rendelkeznek, például azzal, hogy milyen eseményt vált ki a levél kijelölése, vagy egy ikonnal, ami mondjuk egy zárt vagy nyitott boríték, attól függően, hogy a levelet elolvasták-e. Ahhoz, hogy XML-ben jelenítsük meg az elektronikus leveleket, olyan elemcsoportot hozunk létre, amelyből később objektum- vagy tömbgyűjtemény hozható létre az ügyféloldalon történő elemzéskor. Az esemény és az ikon jellemzők hozzáadására itt kerül sor. A jellemzőket egyszerűen lehet az elemekhez adni. Vessünk egy pillantást a 3.2. kódszövegre, hogy megértsük, hogyan adjuk majd az esemény- és az ikonjellemzőket az XML-elemhez:

3.2. kódszöveg Elemek elvont listája (email.xml)

<items action="alert(’Grace Hopper’);" icon="img/mail.gif">

<item><![CDATA[Grace Hopper]]></item>

<item><![CDATA[<b>BUG Found</b>]]></item>

<item>2006-03-31 09:27:26</item>

</items>

Van néhány probléma, amelyekkel nagyon fontos tisztában lennünk a jellemzők használatakor, különösen a nagy alkalmazásoknál, ahol egy tervezéskor vétett hiba nagy károkat okozhat a bővítéskor. A jellemzők egyik legnagyobb problémája, hogy egyetlen jellemzőbe nem lehet több értéket illeszteni. Ez olyankor okozhat gondot, ha később úgy döntünk, hogy egy korábban jellemzőként meghatározott elemből több példányra van szükség. Ilyenkor minden olyan helyen módosításokat kell végeznünk (saját magunknak vagy a fejlesztőtársaknak), ahol a jellemzőkre hivatkozunk.

Egy másik fontos probléma – amelyre a következő részben megoldást találunk – a HTML hozzáadása az XML-hez. A jellemzőkhöz nem adhatunk HTML-t, mert ez érvénytelen szerkezetet eredményezne. XML-szerkezetekhez csak az elemeken belül adhatunk HTML-t. Sokkal biztonságosabb elemet hozzáadni, mint jellemzőt, mert ha később észreveszünk egy hibát, ahol nem a HTML-nek megfelelően formáztuk az elemet, utólag bármikor újraformázhatjuk úgy, hogy HTML-t fogadjon, és ez nem ütközik semmilyen kóddal, ami esetleg az elemre hivatkozik. Ha az elemzést végző programozási nyelv által olvashatóan és az XML érvényességét betartva szeretnénk HTML-t adni az elemekhez, CDATA címkéket kell illeszteni az elemcímkékhez.

CDATA

A CDATA hihetetlenül hatékonnyá teszi az XML-t – és ezáltal az azt használó webalkalmazásokat –, mivel lehetővé teszi, hogy HTML-t adjunk az elemekhez. A HTML segítségével ezután formázott adatokat jeleníthetünk meg, közvetlenül az Ajax-alkalmazás ügyféloldalán szereplő DOM-elemekben. Amikor az általunk használt programozási nyelv elemzi az XML-t, az elemcímkék közötti értékeket is elemzi. A következő példában egy <items> elembe ágyazott <item> elemcsoportot láthatunk:

<items action="alert(’Grace Hopper’);" icon="img/mail.gif">

<item>Grace Hopper</item>

<item>BUG Found</item>

<item>2006-03-31 09:27:26</item>

</items>

Az egymásba ágyazott elemeket az elemzőnek részelemekre kell bontania ahhoz, hogy a programozási nyelv mondjuk gyermekcsomópontokként értelmezze azokat. Ez azt jelenti, hogy nem lehet HTML-címkéket ágyazni az XML-elemekbe, mert az elemző nem HTML-címkékként, hanem a szülőelem beágyazott vagy gyermekelemeiként értelmezi ezeket – ezáltal az XML érvénytelenné válik, ami elemzési hibát vagy nem várt eredményt idéz elő. Az alábbi XML-t látva az elemző a HTML „félkövér” címkéjét (</b>) XML-elemként értelmezi, mert nem HTML-címkékként, hanem beágyazott XML-címkékként látja a félkövér címkéket:

<item><b>BUG Found</b></item>

Ahhoz, hogy HTML-t adjunk az XML-elemhez, CDATA-t kell használnunk. Az XML-elemzők nem elemzik az olyan adatokat, amelyek közvetlenül ezeket a címkéket követik, így érvényes marad az XML-szerkezet és egyúttal az oldalon megjeleníteni kívánt HTML is. Az alábbi kódban érvényes XML-t láthatunk, a CDATA segítségével beágyazott HTML-címkékkel:

<item> <![CDATA[<b>BUG Found</b>]]></item>

Amikor az ügyféloldali parancsnyelv – esetünkben a JavaScript – elemzi ezeket az adatokat, a HTML úgy képeződik le, ahogy a címkék között szerepel. A BUG Found szövegérték például félkövéren jelenik meg a grafikus felületen, ha az adatot beillesztjük a dokumentumba. Ezt úgy tehetjük meg, hogy a DOM segítségével egyszerűen kijelölünk egy HTML-címkét, majd az értéket összekapcsoljuk a JavaScript belső innerHTML tulajdonságával, vagy a document.write(); alkalmazásával közvetlenül arra a helyre írjuk az értéket, ahová a kódsort helyezzük. Most pedig mélyedjünk el jobban a válasz elemzésében!

Az XML elemzése

Amikor az XML-ben használt formázást és címkeneveket tervezzük, több dolgot is fontos szem előtt tartani. Általában hasznos például, ha egyedi neveket adunk a fájlban különböző szinteken elhelyezkedő elemeknek. Így elkerülhetjük a JavaScript belső getElementsByTagName tagfüggvényének használatakor adódó elemzési problémákat. Ez a függvény az összes általunk meghatározott nevű elem tömbjét adja vissza, és nem figyeli, hogy ezek milyen szinten helyezkednek el. Az egyik hiba, ami ebből származhat, az, hogy a különböző szinteken található, nem összetartozó értékcsoportok egyetlen tömbbe kerülnek, amely nem ábrázolja az adatok megfelelő helyét, és ez elemzéskor rémálommá válik számunkra, illetve a fejlesztőtársak számára. Léteznek módszerek az ismétlődő nevekkel rendelkező beágyazott címkéket használó adatok elemzésére, például a childNodes tulajdonsággal történő kijelölés, de ez nehézkes, és hosszabbá teheti a fejlesztési folyamatot. Azt is megtehetjük, hogy olyan objektumot hozunk létre, amely meghatározott elemeket meghatározott szinteken, nevek szerint elemző tagfüggvényekkel rendelkezik, ahogy más nyelvekben az XPATH, vagy jellemzők segítségével különböztetjük meg az azonos névvel rendelkező eltérő csomópontokat. A mi céljainkhoz azonban elég, ha egyszerűen úgy határozzuk meg a szerkezetet, hogy ne kelljen a fenti nehézségek miatt aggódni.

Az XML különböző nyelvű kódokkal való elemzéséhez léteznek teljesen szabványos módszerek, az XML JavaScripttel való elemzése azonban kicsit más. Mint azt korábban említettük, a JavaScriptben létezik egy getElementsByTagName nevű belső tagfüggvény, amely közvetlenül név szerint képes kijelölni egy elemcsoportot, és lehetővé teszi a hozzáférést az elem-, illetve jellemzőértékek egyszerű elemzése érdekében. Ez a függvény egyetlen elemet vagy elemcsoportot ad vissza a paraméter által meghatározott címkenév alapján, ahogy az alábbi példában:

response.getElementsByTagName(’items’);

Amikor a függvény egy elemcsoportot talál, a gyermekcsomópontok tömbjét adja vissza, amelyet elemezni kell ahhoz, hogy megkapjuk a belső csomópontértékeket. Ha ezt az eljárást akarjuk alkalmazni az elemzésben, ügyelni kell, hogy helyesen jelöljük ki az XHR objektumot a válasz elkészülte után. A 3.3. kódszövegre pillantva azt a kész XML-mintát látjuk, amelyet majd elemzési példaként használunk:

3.3. kódszöveg Az e-mail XML fájljának végső változata (email.xml)

<?xml version="1.0" encoding="iso-8859-1"?>

<data>

<categories>

<category>From</category>

<category>Subject</category>

<category>Date</category>

</categories>

<row>

<items action="alert(’Grace Hopper’);" icon="img/mail.gif">

<item><![CDATA[Grace Hopper]]></item>

<item><![CDATA[<b>BUG Found</b>]]></item>

<item>2006-03-31 09:27:26</item>

</items>

</row>

<row>

<items action="alert(’Pi Sheng’);" icon="img/mail.gif">

<item><![CDATA[Pi Sheng]]></item>

<item><![CDATA[Movable type]]></item>

<item>2006-01-15 12:32:45</item>

</items>

</row>

</data>

Az elemzőfüggvények kipróbálásához olyan HTML fájlt kell létrehozni, amelyben két hiperhivatkozás található: az egyik egy XML fájlt kér válaszként, a másik pedig egy JSON fájlt. A 3.4. kódszöveg azt a HTML indexfájlt tartalmazza, amely a kérelmet indító hiperhivatkozásokat tartalmazza:

3.4. kódszöveg Az XML és a JSON kérelemminta indexfájlja (index.html)

<html>

<head>

<title>The Response</title>

<script type="text/javascript" src="javascript/ajax.js"></script>

</head>

 

<body>

<a href="javascript:makeRequest(’services/email.xml’, å onXMLResponse);">xml</a>

&nbsp;|&nbsp;

<a href="javascript:makeRequest(’services/email.js’,

å onJSONResponse);">json</a>

<br/><hr noshade="noshade">

<div id="loading"></div>

<div id="body"></div>

</body>

 

</html>

Láthatjuk, hogy ebben az állományban mindössze két hiperhivatkozás található, amelyekre kattintva kérelmet indítunk a 2. fejezetben létrehozott makeRequest tagfüggvény segítségével. Az egyetlen különbség az, hogy most van egy változó visszahívó függvényünk is, ami lehetővé teszi, hogy tetszés szerinti visszahívó függvényt adjunk át, hogy kedvünk szerint, egy bizonyos kérelem alapján végezzük az elemzést. Két div címke is rendelkezésre áll a különböző adatok megjelenítésére: az egyik címke id (azonosító) értéke loading (töltés), a másiké body (törzs). A loading div a készenléti állapot ellenőrzésekor visszaadott betöltési üzenethez szükséges, a body div pedig a válasz elemzése utáni tényleges adatmegjelenítésre szolgál. Az adatok tetszőlegesen formázhatók: az egyszerű adatlistától kezdve egy műveleti adatokat tartalmazó, XHTML-lel formázott GUI-ig bármilyen formában megjeleníthetők. Az XML-válasz formázása előtt meg kell adni a kérelemben meghatározott visszahívó függvényt. Példánkban egy onXMLResponse nevű függvényt adunk az indexbe betöltött ajax.js-hez, ellenőrizzük a készenléti állapotot, majd az XHR responseXML tulajdonságával jelöljük ki az XML-adatokat (lásd a 3.5. kódszöveget).

3.5. kódszöveg Válaszfüggvény létrehozása és a készenléti állapot ellenőrzése (ajax.js)

function onXMLResponse()

{

if(checkReadyState(request, ’loading’) == true)

{

var response = request.responseXML.documentElement;

//Itt történik az elemzés

}

}

A készenléti állapot ellenőrzésével két dolgot teljesítünk: először ellenőrizzük a kérelem állapotát, hogy kiderítsük, befejeződött-e a töltés, illetve készen áll-e az elemzésre, másodszor pedig átadjuk a div azonosítót a készenléti állapot üzeneteinek az innerHTML tulajdonsággal történő megjelenítéséhez. A 2.1. táblázatban felsorolt tulajdonságok közül kettőt használhatunk az adatok XHR-rel történő kijelöléséhez: az egyik a responseText, a másik a responseXML. A responseText tulajdonság a kiszolgálóról kapott válasz karakterlánc-változatát, a responseXML tulajdonság pedig a kiszolgáló válaszának DOM-megfelelő dokumentumobjektumát adja vissza. Ebben az esetben a responseXML tulajdonságot alkalmazzuk, mivel DOM-megfelelő objektumra van szükségünk az XML-válaszhoz, hogy megkezdhessük az elemek értékeinek elemzését. Először az XML fájl kategóriaértékeit elemezzük, majd az innerHTML tulajdonságon keresztül átadjuk ezeket a body div-nek, a 3.6. kódszövegben látható módon.

3.6. kódszöveg Kategóriaértékek kigyűjtése az XML-ből (ajax.js)

//Kategóriák

document.getElementById("body").innerHTML = "------------<br/>";

document.getElementById("body").innerHTML += "<b>Categories</b><br/>";

document.getElementById("body").innerHTML += "------------<br/>";

 

var categories = response.getElementsByTagName(’category’);

for(var i=0; i<categories.length; i++)

{

document.getElementById("body").innerHTML +=

å response.getElementsByTagName( å ’category’)[i].firstChild.data +"</br>";

}

Az egyes kategóriák kijelöléséhez a getElementsByTagName tagfüggvényt kell alkalmaznunk, és a category értéket kell átadni paraméterként. Így egy kategóriatömböt kapunk eredményül, amelynek elemeit egyenként a body div-hez adhatjuk. A kategóriák hozzáadásakor az összes címkékben szereplő adatot kijelöljük, hogy minden elem tényleges értékét megjelenítsük.

A kategóriák megjelenítése után továbbléphetünk az XML item (elem) címkéire. Ezeket kissé eltérően elemezzük, a szülők, vagyis a row (sor) címkék kijelölésével, amivel egy sorokból álló tömböt kapunk. Ezután a sorokat bejárva a JavaScript belső getAttribute tagfüggvényének segítségével az items címkékben szereplő action (művelet) és icon (ikon) jellemzőket jelöljük ki. Miután befejeztük a jellemzőértékek div-be írását, önálló elemeket jelölhetünk ki az egyes sorokban. Ezt úgy hajtjuk végre, hogy két for ciklust ágyazunk a soroknál használt for ciklusba, ezáltal egy háromrétegű ciklust kapunk. Az egyik ciklus az items címke, a másik pedig az egyes item címkéken belül szereplő csomópontértékek bejárására szolgál, a 3.7. kódszövegben látható módon.

3.7. kódszöveg Elemértékek kigyűjtése az XML-ből (ajax.js)

//Elemek

document.getElementById("body").innerHTML += "------------<br/>";

document.getElementById("body").innerHTML += "<b>Items</b><br/>";

document.getElementById("body").innerHTML += "------------<br/>";

 

var row = response.getElementsByTagName(’row’);

for(var i=0; i<row.length; i++)

{

var action = å response.getElementsByTagName(’items’)[i].getAttribute(’action’);

var icon = å response.getElementsByTagName(’items’)[i].getAttribute(’icon’);

document.getElementById("body").innerHTML += å action +"<br/>"+ icon +"</br>";

var items = response.getElementsByTagName(’items’)[i].childNodes;

for(var j=0; j<items.length; j++)

{

for(var k=0; k<items[j].childNodes.length; k++)

{

document.getElementById("body").innerHTML +=

å items[j].childNodes[k].nodeValue +"</br>";

}

}

document.getElementById("body").innerHTML += "------------<br/>";

}

A kért XML elemzése meglehetősen egyszerű, ha tudjuk, hogy a kiszolgáló válasza milyen formátumban várható. Ha az előző példaválaszban nem tudtuk volna, mire számítsunk, kezdetnek a responseText tulajdonság alkalmazásával karakterláncként megjeleníthettük volna a szerkezetet, hogy megfejtsük, milyen címkéket kell kijelölni:

function onXMLResponse()

{

if(checkReadyState(request, ’loading’) == true)

{

var response = request.responseText;

alert(response);

}

}

Így a teljes XML-szerkezetet egy figyelmeztető üzenetben kaptuk volna meg. Ezután már meg lehet nézni a szerkezetet, és el lehet dönteni, hogy mit akarunk elemezni a responseXML tulajdonság segítségével.

Láthatjuk, hogy az XML gyakorlatilag bármilyen adatszerkezetet képes megvalósítani, és valójában az XML-t olvasó objektumokon múlik, hogy valami hasznosat kezdjenek vele. Vizsgáljuk meg, hogy ehhez képest milyen a JSON, és hogy milyen előnyöket nyújt a válaszok formázásakor.

JSON

A JSON, azaz JavaScript Object Notation (JavaScript objektumjelölés) adatcsere-formátum egyre szélesebb körben elfogadott, mint az Ajax-alkalmazások egy lehetséges formátuma. Lényegében egy társításos tömb vagy hasítótábla, attól függően, hogy melyik programnyelvben mozgunk a legotthonosabban. Ez azt jelenti, hogy a nevek, illetve címkék értékekhez rendelődnek egy tömbszerkezetben vagy vesszőkkel tagolt listában. Az egyszerű nyelvtannak és a JavaScript szabványos ügyféloldali parancsnyelvként történő átvételének köszönhetően ez a formátum az Ajax-alkalmazásokban használt adatformátumok között felveszi a versenyt az XML-lel. Ezen kívül a JSON-elemzést támogatja a JavaScript eval tagfüggvénye, ami rendkívüli módon megkönnyíti az elemzést, ha az Ajax-alkalmazásunkban használjuk. Vannak azonban buktatói is: az eval alkalmazása miatt nagyon lelassulhat az elemzés, és ami még fontosabb, az eval a biztonság szempontjából nagyon veszélyes lehet. Ez szerencsére nem jelenti azt, hogy a JSON kiesik az Ajax adatcsere-formátumainak versenyéből, csupán az a lényeg, hogy körültekintőbbnek kell lennünk, amikor ezt választjuk adatformátumként. Többek között úgy lehetünk elővigyázatosak, ha titkosított jelszavakat adunk a kérelmekhez, ahogy azt a 23. fejezetben majd láthatjuk.

Most, hogy már rendelkezünk némi ismerettel a JSON-ról, lássuk, hogy milyen nyelvtant kell követnünk a szerkesztésekor.

A JSON nyelvtana

A JSON nyelvtana rendkívül egyszerű, és igazolhatóan könnyebben kezelhető, mint az XML-é. Az XML az elemek ismétlődése miatt meglehetősen nehézkes sok adat kezelésénél, ezért ilyenkor a JSON remek választás lehet. A JSON nem szabványos adatcsere-formátum, de a sok rendelkezésre álló elemző miatt járható utat jelent. A http://www.json.org címen szinte az összes JSON-elemző fellelhető, de ha nem találunk az adott nyelvhez tartozó elemzőt, könnyen írhatunk egyet, hiszen a nyelvtan elemzése nem túl nehéz.

A JSON nyelvtana objektumközpontú szemlélettel vizsgálva könnyen befogadható. A JSON fájlok szerkezete megfelel a JavaScript-objektumokénak, abból a szempontból, hogy egy fájl több objektumból, tömbből, karakterláncból, számból és logikai értékből állhat. A 3.1. táblázat JSON-ként formázott adattípusokat sorol fel.

3.1. táblázat Az egyes adattípusok JSON-megfelelői

Adattípus JSON ábrázolás

Karakterlánc "icon": "img/mail.gif"

Szám "mynumber": 100

Logikai érték "myboolean": true

Tömb "items": [ { "action": "alert(’Grace Hopper’);", "icon": "img/mail.gif", "item": ["Grace Hopper", "<b>BUG Found</b>", å "2006-03-31 09:27:26"] },

{ "action": "alert(’Pi Sheng’);", "icon": "img/mail.gif", "item": ["Pi Sheng", "Movable type", å "2006-01-15 12:32:45"] } ]

Objektum "categories": { "category": ["From", "Subject", "Date"] }

Az egyes JSON-adattípusokat egy név vagy egy címke jelöli, amely után kettőspont áll. Csak az értékek változnak típusonként. Az egyszerűbb típusok egyértelműek: a karakterlánc értékeket karakterláncok jelölik, a számokat számok, a logikai értékeket pedig a true (igaz) vagy a false (érték). A tömbök és az objektumok bonyolultabb adattípusok. A tömböket szögletes zárójelek között álló, vesszőkkel tagolt lista képviseli. A JSON-objektumok bármilyen adattípus tulajdonságait tartalmazhatják – ezek kapcsos zárójelek között állnak, úgy, ahogy más nyelvekben az osztályokat formázzák. Annyi a különbség, hogy itt nem adunk nevet a fő szerkezetnek.

A JSON használata

A JSON nyelvtanának megértése után a formázás meglehetősen egyszerű. Ha nagy menynyiségű adattal dolgozunk, érdekes összehasonlítani a JSON és az XML formátumot, mert a JSON végül kisebb adatszerkezetet eredményez. Ebben a részben átalakítjuk az XML rész példáit, és a két formátumot összehasonlítva megnézzük, hogy méret és olvashatóság szempontjából mennyire térnek el egymástól. Az összehasonlítások elvégzése után a következő részben a JSON-adatszerkezetek elemzésével foglalkozunk. A 3.8. kódszöveg adatszerkezete az előző részben szereplő XML fájl átalakított változata.

3.8. kódszöveg A kész JSON mintaformátum (email.js)

{

"data":

{

"categories":

{

"category": ["From", "Subject", "Date"]

},

 

"row":

{

"items":

[

{

"action": "alert(’Grace Hopper’);",

"icon": "img/mail.gif",

"item": ["Grace Hopper", "<b>BUG Found</b>", "2006-03-31

09:27:26"]

},

{

"action": "alert(’Pi Sheng’);",

"icon": "img/mail.gif",

"item": ["Pi Sheng", "Movable type", "2006-01-15 12:32:45"]

}

]

}

}

}

Láthatjuk, hogy ez sokkal kevesebb, mint az XML változatban, mert a címkék az XML-szerkezettől eltérően itt nem ismétlődnek feleslegesen. Ne feledjük, hogy ez a fájl sokkal tömörebb is lehet, csak a jobb olvashatóság kedvéért jelenítettük meg így. A JSON adatszerkezet megközelítőleg 200 karakterrel rövidebb: összesen 316 karakterből áll, míg az XML formátum 519 karakter hosszú – ami igen nagy különbség. Ahogy az alkalmazásban szereplő adatok sokasodnak, ez sávszélesség-problémákhoz vezethet, de ahogy korábban említettük, a JSON-nal lassabb lehet az ügyféloldali elemzés. Végül el kell dönteni, hogy melyik formátum használhatóbb az adott alkalmazásban, illetve hogy számunkra melyiket könnyebb elemezni és írni.

A JSON elemzése

A JSON XHR-ből származó válaszként való elemzése eltér az Ajax-szal használható összes többi adatcsere-formátum elemzésétől. Az XML-nél alkalmazott responseXML tulajdonság helyett a responseText tulajdonságot kell használni. Ezt a tulajdonságot rendkívül egyszerű sima szöveggel vagy tiszta XHTML-lel alkalmazni, mert egyedül ezt használjuk a válasz értékeként, ahogy a következő példában is:

document.write(request.responseText);

A responseText tulajdonság JSON-nal történő alkalmazása szintén egyszerű; csupán annyi a különbség, hogy ki kell értékelni ahhoz, hogy olvasható legyen az elemzéshez. A válasz kiértékelésével lényegében létrehozzuk az adat JavaScript-objektumát, amelyet azután az ügyféloldalon a GUI megjelenítési adataiként használhatunk. Az adatok elemzéséhez először létrehozzuk a visszahívó függvényt, ellenőrizzük a kérelem készenléti állapotát, majd kiértékeljük a responseText-et (lásd a 3.9. kódszöveget).

3.9. kódszöveg Válaszobjektum létrehozása (ajax.js)

function onJSONResponse()

{

if(checkReadyState(request, ’loading’) == true)

{

eval("var response = ("+request.responseText+")");

}

}

Ahogy azt a fejezet XML-lel foglalkozó részében tárgyaltuk, a checkReadyState tagfüggvény két célra használható: a válasz teljes betöltődésének ellenőrzésére, valamint betöltési üzenet megjelenítésére a felhasználó számára, bármilyen paraméterként meghatározott HTML-elemben. A válasz teljes betöltődése után az XHR-ből származó responseText kiértékelésével kezdjük az elemzést, valamint létrehozunk egy response nevű objektumot az eredmény számára. Ez az objektum ezután képes bármilyen, a kiértékelés vagy az adatok elemzése során hozzáadott értéket kijelölni. Kezdjük azzal, hogy kijelöljük az adatokból a kategóriákat, majd az indexfájlban szereplő body div-hez adjuk azokat (lásd a 3.10. kódszöveget).

3.10. kódszöveg A JSON-kategóriák elemzése (ajax.js)

//Kategóriák

document.getElementById("body").innerHTML = "------------<br/>";

document.getElementById("body").innerHTML += "<b>Categories</b><br/>";

document.getElementById("body").innerHTML += "------------<br/>";

 

for(var i in response.data.categories.category)

{

document.getElementById("body").innerHTML +=

å response.data.categories.category[i] +"<br/>";

}

Láthatjuk, hogy miután JavaScript-objektummá alakítottuk az adatokat, már könnyű kijelölni azokat. A tulajdonságértékeket egyszerűen, pont jelöléssel lehet elérni. A 3.10. kódszövegben olyan kategóriákat jelölünk ki, amelyek tömbök, mivel a category tulajdonságban több érték szerepelt. A kategóriatömb kijelöléséhez pont jelölést alkalmazunk, amellyel szó szerint útvonalat rajzolunk a válaszobjektum egy adott tulajdonságához.

Most, hogy megtörtént a kategóriák elemzése és a body div-ben történő megjelenítése, kijelöljük az elemeket. Ehhez két for ciklust kell beágyazni, csakúgy, mint az XML-példában, de a tényleges értékek elemzése kissé eltér majd a valódi elemek és a jellemzőik esetében. A 3.11. kódszövegre tekintve megérthetjük, miként elemezzük ezeket az adatokat.

3.11. kódszöveg JSON-elemek elemzése

//Elemek

document.getElementById("body").innerHTML += "------------<br/>";

document.getElementById("body").innerHTML += "<b>Items</b><br/>";

document.getElementById("body").innerHTML += "------------<br/>";

for(var i in response.data.row.items)

{

 

for(var j in response.data.row.items[i])

{

document.getElementById("body").innerHTML +=

å response.data.row.items[i][j]+"<br/>";

}

document.getElementById("body").innerHTML += "------------<br/>";

}

Ahogy korábban említettük, az elemjellemzőket teljesen eltérő módon jelöljük ki, mint az XML-elemzésnél. Egy egyszerű for...in ciklussal kijelölhetjük az összes tulajdonságértéket egy adott objektumon belül. Ezúttal az adatgyűjtés ezen módszerét használjuk az elemjellemzők és az elemtömbök értékeinek eléréséhez.

A JSON válaszformátumként történő alkalmazása még hatékonyabb lehet, ha az adatformátumon belül eseménykezelőket határozunk meg, amelyek a dokumentumra leképezhető bizonyos objektumtípusokat képviselnek. Ezt nem tárgyaljuk részletesen, de fontos, hogy tudjunk róla, mert nagyon hasznos lehet a későbbi alkalmazásokban. Elégedjünk meg egy példával, amely bemutatja, milyen megközelítésben kell szerkeszteni az ilyen adatokat:

"items": [

{"value": "Read e-mail", "onclick": "displayEmailDetail()"}

]

Most, hogy bővebb ismeretekkel rendelkezünk az Ajax-válaszok kezeléséről, összpontosítsunk a grafikus felhasználói felület CSS-sel vagy XHTML-lel történő létrehozására, illetve formázására.

 

Vissza a könyv részletes adataihoz