Bizonyára sokatok számára ismerős az a helyzet, amikor olyan funkciót kell készíteni, ami másodpercenként vagy percenként frissít tartalmat. Például egy üzenőfal vagy egy értesítő.
A legegyszerűbb megoldás, egy setInterval()-féle függvény, amit x időközönként meghívsz. Ennek viszont az a nagy hátránya, hogy valószínűleg nem minden x-edik időben következett be változás a frissítendő tartalomban, így feleslegesen terhelődik a kliens és akár a szerver is. Akadhatnak olyan esetek is, amikor gyakorlatilag valós időben kell tartalmat frissíteni, ha valamilyen változás történt az adatokban, mint például a csevegő alkalmazások esetében. Az előbbi példával élve ez egy-egy néhány másodpercenként lefutó függvényt jelentene, ami rengeteg felesleges művelettel járna és nem is lehetne valós idejűnek nevezni. Ehhez hozzájárul még az is, hogy a böngészők csak néhány kapcsolatot engednek egyidejűleg nyitva tartani, ami szintén lassabbá teheti az oldalad.
Csöbörből vödörbe
Az egyik leggyakrabban használt módszer a valós idejű reagálásra az úgynevezett „Long-polling” technika, ami az AJAX alapjaira épül, így aszinkron kommunikációval valósul meg. Ennek lényege, hogy a szerver egy ciklusban ellenőrzi, hogy történt-e változás, de a ciklus nem a végtelenségig fut – meg kell adni neki egy bizonyos lépésszámot, ami után el kell döntenie, hogy volt változás vagy sem. Ha történt változás, akkor elküldi válaszban AJAX-on keresztül, majd újra meghívódik, viszont ha nem, akkor üres választ ad és ismét meghívódik (a korlátozott számú egyidejű nyitott kapcsolat miatt). Ez a folyamat a háttérben zajlik, így a felhasználót nem befolyásolja semmiben sem, de sajnos ennek továbbra is az a hátulütője, hogy feleslegesen hajtunk végre műveleteket a szerveren. Például a ciklusban mindig lekérdezünk egy adatbázistáblát, hogy megvizsgáljuk, történt-e benne változás.
Hogyan kényszeríthetnénk a szerveroldalt esemény alapú I/O műveletekre?
2009-ben született meg a nyílt forráskódú Node.js, melyet úgy alkottak meg, hogy kéréseket fogadjon és válaszokat küldjön aszinkron módon. Ahogyan azt már sejtheted, ez egy JavaScript alapú rendszer, melyhez a Google kifejlesztette a szintén nyílt forráskódú V8 JavaScript futtató motort. A Node.js kiválóan alkalmas a túlterhelés minimalizálására és a skálázhatóság növelésére, hiszen eseményvezérelt a működése, így elég csak akkor műveletet végeztetni vele, ha történt valami, amire reagálni kell. Például egy csevegő alkalmazásban a csevegő felek egyike új üzenetet küldött, amit a szerver eltárol, maga az üzenet küldése pedig kivált egy eseményt a szerveren és erre az eseményre reagálva a többiek számára is elküldi az új üzenetet.
Hogyan tovább?
Annak érdekében, hogy a kommunikáció kétoldalú, duplex és kéréstől független legyen, létrehozták a WebSocketet, mely ma már a W3C szabványok közé tartozik. A kapcsolatok kiépítésekor a kliens egy kézfogási kérelmet (handshake request) küld, amire a szerver kézfogási válasszal reagál. A kézfogás a HTTP-re hasonlít, de valójában nem az – lehetővé teszi azonban, hogy a szerver a kézfogási kérelmet a HTTP protokoll szerint értelmezze, majd átválthasson a WebSocket használatára. Sajnos nem teljes a támogatottsága, mivel az Internet Explorer 10 előtti verzióiban nem használható – ki gondolta volna? – és nagy sajnálatra az Android böngészők 4.4 előtti verzióiban sem működik. Nem kell pánikba esni, nincs minden veszve, ugyanis nem feledkeztek meg azokról sem, akik még a régebbi Internet Explorereket vagy Android böngészőket nyúzzák!
Az optimális megoldás a Socket.io, amely remekül használható a Node.js-sel együtt. Kétirányú eseményvezérelt kommunikációt hivatott létrehozni valós időben, melyhez a korábban említett WebSocketet használja elsődlegesen, illetve rendelkezik egy polling visszakapcsolással (fallback) a korábban említett támogatottsági problémák miatt. A Socket.io hivatalos oldalán egy egyszerű, valós idejű chat segítségével nézheted meg, hogy mire is képes a cucc. A chat forráskódja megtalálható a letöltött Socket.io-ban példaként, illetve a hivatalos oldalon találhatóak további egyszerűbb példák a működésére és használatára vonatkozóan. Léteznek még alternatívák, amelyek hasonlóképpen működnek, úgymint az Actionhero.js, Elephant.io, és még ezeken kívül is van jó néhány.
Manapság nagy szerepe van az optimalizálásnak, egyrészt az oldalak betöltési sebessége, másrészt a gördülékeny, felhasználóbarát működés miatt, és persze az erőforrás megtakarítás sem utolsó szempont. Érdemes jól átgondolni a megvalósítást és a használt technológiákat mielőtt nekikezdesz a funkciók megvalósításának.
Hozzászólások