JavaScript: aszinkron adatlekérés

3. Aszinkron hívások

Az erőgyűjtés utolsó részében arról lesz szó, hogy miképpen lehet Javascript segítségével távoli szerverektől adatot lekérni az oldal újratöltése nélkül.

1

AJAX bevezetés

A modern honlapok esetében nem lehet mindent statikus oldalakkal megoldani, ahogy az sem várható el, hogy minden információt a szerver határozzon meg. Az eddigiekben, bár az oldal tartalmát Javascript segítségével tudtuk változtatni, a tényleges adatok mindig ugyanazok voltak. Manapság egyre gyakoribb viszont, hogy a weboldal csak kevés információ birtokában töltödik be, és ha új adat kezelésére van szükség, azt a szervertől utólag kéri le. Itt jönnek a képbe az XML HTTP lekérések és az AJAX.

A távoli lekérés lényege, hogy a Javascript kód egy XMLHttpRequest-et küld a szervernek, amire az válaszol, jellemzően szöveges formátumban. Ez lehet egy egyszerű szöveg is, de mivel jellemzően strukturált adatok lekérésére használjuk, ezért a formátum is ennek megfelelő, tipikusan XML, vagy újabban JSON. Mi most az XML-es verziónál maradunk. A következő kódrészlet bemutatja egy alapvető XMLHttpRequest küldését és a válasz fogadását:

A kódrészletet egy függvénybe foglaltuk, hogy tetszés szerint meghívhassuk. Először létre kell hozni a kérést kezelő objektumot. Az open függvény segítségével megadhatjuk a kapcsolat adatait, mint a cél (jelen esetben egy, az azonos szerveren található ajax_info.txt fájl), illetve az adatküldés típusa (GET vagy POST, mint a form-ok esetében is). A harmadik paraméter igazra van állítva, hogy a hívás aszinkron legyen, és közben a weboldal működése ne fagyjon le. A send() hatására a kérést elküldjük. Már csak a második utasítás maradt ki. Egy ilyen kérés megvalósítása több lépéses, és ezen a ponton egy függvényt rendelünk a kérés állapotának figyeléséhez. Most csak a legvége érdekel minket, de minden állapotváltozásra reagálhatunk ezzel, ha szeretnénk. Ellenőrizzük, hogy a kérés állapota az legyen hogy megjött a válasz (ez a 4-es kód), valamint hogy sikeres legyen a kérés (amit a 200-as status kód jelöl). Ilyenkor tudunk a sikeresen visszakapott válasszal dolgozni, amit a példakód egyszerűen kiír az oldalra.

Ezzel az egésszel a probléma a gyakorlatban lesz, hiszen az ilyen webldalak mögött általában áll egy webszerver is, amelyiktől le tudják kérni az adatokat. Esetünkben viszont ilyen szerver nem áll rendelkezésre. Szerencsére az interneten elég sok szervert lehet találni, amitől távoli kérésekkel adat szerezhető, így ezekre fogunk a későbbiekben támaszkodni.

Nézzünk is egy tényleges példát. Célpontnak szinte bármit meg lehet adni, azonban mivel a mi kódunk mögött nincs egy szerver, és nem a saját szerverünktől kérünk adatot, korlátokba ütközhetünk. Az olyan kéréseket, amikor másik szerverhez intézünk távoli kérést, Cross-Origin Resource Sharing-nek nevezik, és a probléma az, hogy sok szerver nem engedélyezi ezeket. Erre szerencsére lehet megoldást találni, és az egyik legegyszerűbb az, ha egy proxi-ként üzemelő köztes szervert használunk. Ilyen például a CORS Anywhere szerver, ahogy a lentebbi példakódban is látható. Egyszerűen a megadott cím után kell fűzni az általunk lekérni kívánt címet, és meg tudjuk kerülni a problémát.

« Előző | Lap eleje

2

XML fájlok kezelése

Ahogy már említettük, az XML-ben megfogalmazott válasz egy gyakori formája a távoli lekéréseknek. Ehhez segítséget az alábbi oldal nyújt. Ez esetben viszont a kapott xml-t értelmezni kell. Erre Javascriptben egy megoldást az XML DOM nyújt, a részletes függvénylista itt található.

A lentebbi egyszerű példa szemlélteti az XML értelmezését, ahol már távoli lekéréseket használva a BoardGameGeek oldal által biztosított API egyik funkcióját használjuk, amivel társasjátékokra lehet rákeresni név alapján. Az API leírása itt található.

Figyeljük meg az XML válasz értelmezésének módját. Az XML-t megnézve láthatjuk, hogy a találatok egymás után, boardgame tag-gel megjelölve szerepelnek. Az objectid attribútum az azonosító, amivel lehet a játékokra hivatkozni. Ezután ennek gyerekeiként szerepel egy name tag, ami a játék nevét tárolja, valamint egy yearpublished tag, ami a kiadás évét. Érdekes látni, hogy bár ezen tag-ek között csak egy-egy szöveg szerepel, ezeket mégis úgy lehet elérni, mint az adott tag-ek egyetlen gyerekét, amiknek aztán lekérjük az értékét.

« Előző | Lap eleje

3

Oldd meg a feladatokat!

Kedves Bakonyi Bitfaragó Jelöltek!

Ebben a részben megismerkedhettetek a távoli lekérésekkel, valamint az XML feldolgozásával. Most következzen tehát a beadandó feladat, ahol a BoardGameGeek API egyéb funkcióinak használatával egy összetettebb társasjáték-kereső valósítható meg. Ehhez három funkció használata lesz szükséges. Az egyik a játékok keresése név alapján, amit már az előző fejezet tárgyalt. Itt a keresett szót / szavakat a "http://www.boardgamegeek.com/xmlapi/search?search=" link után fűzve lehet a keresést végrehajtani. Például "http://www.boardgamegeek.com/xmlapi/search?search=Crokinole".

A másik funkció az egy játék adatainak a részletes lekérése, ahol a "http://www.boardgamegeek.com/xmlapi/boardgame/" link használatos, miután a végére fűzzük a játék azonosítóját. Szükség lesz a statisztikákra is, tehát "?stats=1" kell majd a link végére. Például: "http://www.boardgamegeek.com/xmlapi/boardgame/194879?stats=1".

A harmadik funkció egy felhasználóhoz tartozó játékok lekérése. Ez nem feltétlenül azt jelenti, hogy a neki meglévő játékok listája, hanem lehetnek a játékok amivel játszott, vagy hogy mit szeretne megvenni, stb. Ebből a nagy gyűjtmeményből lehet szűrni. Itt egy példa link így néz ki: "http://www.boardgamegeek.com/xmlapi/collection/zefquaavius?own=1". A collection után jön a felhasználónév. Ha csak ennyit írunk, akkor minden játék megjelenik, amivel valamilyen módon kapcsolatba került a felhasználó. Ha szűrni szeretnénk a listát, akkor egy paramétert is adunk, ami alapján szűrünk. Az own paraméter az alapján szűr, hogy megvan-e neki a játék, az 1 pedig azt jelenti hogy csak a meglévőket listázza ki.

A játék adainak lekérése egy nagyobb XML kódot ad vissza, amiből a feladat csak egy kicsi rész fog felhasználni. A következő adatokra lesz szükség:

A játékos-gyűjtemények kezelésénél nem lesz szükség sok információra. A gyűjtemény item tag-ekből áll, mindegyikből csak a játék name tag által jelölt neve lesz az érdekes.

A szerver által biztosított API esetében furcsa módszert választottak a sokáig tartó lekérdezések kezelésére. Ilyenkor a szerver a lekérést a háttérben végzi el, és az eredmény elmenti. A kérésre érkező válasz azonban csak egy egyszerű üzenet:

Ilyen esetben ez nem is fog változni, viszont egy későbbi lekérés alkalmával, amennyiben ezt az eredményt már meghatározta és még tárolja, akkor már vissza tudja adni az eredményt. Az üzenet a lekérés típusa alapján változhat, a szövege nem mindig ugyanez.

Beküldhető feladatok:

  1. Az eddigiek alapján tehát készítsétek el a következő feladatokat:
    • A weboldal egy játék-kereső legyen, ahol a keresett név-részleteket be lehet írni valahova, és az oldal kilistáz minden megtalált játékot.1000|2 pont
    • A találatok kerüljenek be egy listába, amiből később ki lehet majd választani egy elemet.1000|2 pont
    • A lista egy elemét kiválasztva, annak az adatait a játék-adatokat lekérő kéréssel kérje le és gyűjtse ki az oldal.100 0000|2 pont
        Minden korábban említett adat strukturált, áttekinthető formában jelenjen meg az oldalon úgy, hogy a találatok listája nem tűnik el.
        A megjelenítés legyen szebb, mint egy egyszerű szöveg, pl. látszódjon a kép, az értékelés lehet valami csillagos skála, stb.
    • Az oldalon legyen egy olyan rész is, ahol egy felhasználó gyűjteményét lehet megnézni.10 0000|2 pont
        A szűréshez lehessen megadni egy felhasználónevet szövegként, kiválasztani listából a szűrés típusát (vagy semmit),
        valamint hogy a 0 vagy az 1 értékekre szűrjünk. A szűrés típusához nem kell az összes lehetőséget kezelni, elég az API által felsorolt első 8-at (a wishlist-ig).
        Ha a teszteléshez több felhasználónév is kell, akkor itt lehet keresni.
    • A weboldal kezelje le azt, ha a választ nem kapja meg egyből a szervertől.100 0000|2 pont
        Ilyen esetben nem szabad a korábban mutatott kicsi XML-t válaszként feldolgozni, hiszen az csak türelemre int.
        Ekkor a böngészőnek várnia kell egy kicsit, és 5 másodperc múlva újra elküldeni a kérést abban a reményben, hogy ezúttal rendes választ kap.
        A próbálkozást csak akkor szabad abbahagyni, ha már 4 egymás után próba is után sincs rendes válasz.
        Ekkor ki kell jelezni, hogy a szerver nem tudott időben választ adni a kérdésre.

    Összesen 1011 0000|2 pont

« Előző | Lap eleje

Hivatkozások, felhasznált források

[1] Mozilla developer network: DOM

[2] CSS alapjai I.

[3] AJAX leírás

[4] XML leírás