V minulém článku o AppCache jsme si ukázali možnosti, které mají moderní prohlížeče v oblasti cachování skriptů a souborů na straně klienta. Ukázali jsme si, jak lze celkem jednoduše určit, že mají být soubory uloženy lokálně, které to mají být a jak s nimi nakládat. Ovšem většina aplikací potřebuje nejen ukládat stránky, skripty a další soubory („program files“), ale i nějak ukládat vytvořená data. A pokud má fungovat offline (nebo rychle), musí k tomuto účelu mít lokální úložiště. Technologie z rodiny HTML5 nabízí hned několik řešení, v tomto článku se podíváme na jedno z nich, konkrétně WebStorage.
WebStorage
Pravděpodobně nejjednodušší a nejrozšířenější technologií lokálních úložišť je WebStorage – podle webu Can I Use můžeme použít WebStorage v nových verzích všech hlavních prohlížečů (IE od verze 8, FF od 3.0, Safari od 4.0, Chrome od 3.0 a Opera od verze 10.5), i když to s tou podporou není stoprocentní, jak si řekneme dál – pozn.aut.
Web Storage definuje dvě lokální úložiště, které jsou identické až na jednu věc, a tou je jejich perzistence. První úložiště, zvané LocalStorage, ukládá data v prohlížeči „napořád“ – tedy dokud nejsou skriptem smazány. Druhé úložiště, SessionStorage, ukládá data jen po dobu trvání sezení (session), tedy zhruba řečeno po dobu než uživatel zavře prohlížeč, okno nebo záložku s danou stránkou. Specifikace výslovně dodává, že „trvání sezení“ nemusí být totožné s dobou otevření příslušného okna či záložky a že některé prohlížeče mohou nabízet i pokračování v sezení po restartu.
Úložiště pracují jako jednoduchá key-value
databáze a jejich fungování lze připodobnit k „asociativním polím“ – tedy polím dat, které jsou indexovány nikoli celočíselnou hodnotou, ale obecným klíčem, nejčastěji řetězcem. Tato pole existují ve většině moderních jazyků, i když pod různými názvy – asociativní pole, slovníky či hash arrays jsou nejčastější pojmenování.
Ukládání v prohlížeči podle klíčů může připomínat cookies, ovšem je tu jeden zásadní rozdíl: Cookies jsou primárně určeny pro data, která si chce server uložit do klientského prohlížeče pro své účely (i když jsou přístupné ze skriptu, běžícího v prohlížeči). Posílají se v hlavičkách HTTP dotazů a odpovědí a jejich velikost je omezená. Data uložená ve WebStorage naproti tomu zůstávají v prohlížeči, nikam se neposílají a o případné uložení na server se musí programátor postarat sám.
Specifikace rovněž neurčuje velikost těchto úložišť a nechává správu a případné omezení kapacity na tvůrcích prohlížečů. Nelze se tedy spoléhat na to, že existuje nějaká „specifikací daná minimální nebo maximální kapacita“. Doporučená velikost úložiště je 5MB pro každý zdroj (doménu).
Umí váš prohlížeč WebStorages? Zjistíte to rychle a přehledně v našem detektoru podpory technologií z rodiny HTML5. Naleznete v něm i odkazy na další články, které se zabývají tímto tématem.
Bezpečnost a konzistence dat
Podobně jako u cookies a JavaScriptu platí i pro WebStorage pravidlo same origin na základě domény, a specifikace doporučuje tvůrcům prohlížečů postupy, jak zabránit neoprávněným skriptům přistupovat k uloženým datům. Pro hostingy, které nabízí běh webů pro různé uživatele na společné doméně, jako byl třeba známý server Geocities, se použití WebStorage nedoporučuje – specifikace podotýká, že i kdyby některý prohlížeč implementoval ochranu podle cesty k souboru, tak existují způsoby, ji jak pomocí manipulace s DOM obejít.
Na tomto místě je vhodné podotknout, že Local Storage je opravdu sdílené pro celý zdroj. Pokud si uživatel otevře tutéž stránku v několika oknech či panelech, tak všechny přistupují k jednomu úložišti. Pokud tedy skript v jednom okně změní data, uvidí tyto změny i skripty v dalších otevřených oknech. Totéž platí např. i pro obsluhu událostí: Pokud ve skriptu obsluhujeme událost storage
, viz dále, a uživatel si aplikaci otevře v několika oknech, pak změna dat v jednom z nich vyvolá obsluhu této události ve všech.
Ohledně konzistence dat je důležité vědět následující: Specifikace nepožaduje, aby změny byly ihned ukládány na disk. Pokud si prohlížeč ukládá změny do cache v paměti a havaruje před jejím uložením na disk, může uživatel o data přijít. Specifikace vyžaduje pouze konzistenci dat při paralelním přístupu z více oken najednou (viz předchozí odstavec).
Programové rozhraní – API
K WebStorage lze přistupovat pomocí několika metod a vlastností, definovaných v rozhraní Storage
. Jednotlivé položky jsou identifikovány jedinečným řetězcem – klíčem.
setItem(key, value)
umožňuje nastavit položku s klíčemkey
(typ řetězec) na hodnotuvalue
(obecný objekt). Jako v jiných jazycích i zde je existující položka se zadaným klíčem přepsána, neexistující vytvořena. Pokud nemůže být vytvořena, vyvolá metoda výjimkuQUOTA_EXCEEDED_ERR
. Technicky je při ukládání nejprve vytvořen klon (structured clone) předaného objektu a ukládán je až ten. OperacesetItem()
je atomická, tzn. pokud dojde v jakékoli fázi provádění k chybě, je vyhozena výjimka a uložená data zůstanou beze změny.getItem(key)
slouží ke čtení uložené hodnoty. Pokud položka s daným klíčem neexistuje, je vrácena hodnotanull
.removeItem(key)
odstraní položku s daným klíčem z úložiště. Pokud neexistuje, neudělá nic. IremoveItem()
je, podobně jakosetItem()
, atomická operace.clear()
slouží k vyčištění úložiště – pokud obsahuje nějaká data, jsou odstraněna.key(index)
vrátí klíč N-té položky v úložišti. Položky jsou interně číslovány od nuly a jejich počet můžeme zjistit z vlastnostilength
. Pomocíkey()
alength
můžeme tedy iterativně procházet uložené položky, podobně jako u jiných kolekcí v JavaScriptu.
Úložiště nabízí i již zmíněnou vlastnost length
. Ta je určena pouze ke čtení, a jak už její název napovídá, dozvíme se z ní počet položek, uložených v úložišti.
Při změnách v úložišti je vyvolána událost storage
. Tuto událost můžeme běžným způsobem zachytit a zjistit z ní informace o proběhlé operaci. V těle události nalezneme pak následující atributy:
key
– klíč položky, které se operace týkalaoldValue
– původní hodnota položky (byla-li měněna existující), nebo null, pokud byla položka vytvořena nověnewValue
– nová hodnota položkyurl
– URL stránky se skriptem, který vyvolal událoststorageArea
– oblast, v níž došlo ke změně (local/session storage)
Poznámka a oprava: Událost storage
zatím není v některých prohlížečích implementována zcela správně. Např. FF3.6.8 událost vyvolá, ale hodnoty jsou undefined, v Chrome 5.0.375 událost nebyla vyvolána. V současnosti tedy není obsluha události storage všeobecně použitelná (lze ji ale např. použít ve webových aplikacích pro iPhone), i když prohlížeče úložiště samotné implementují.
Aktualizace: V komentářích se objevilo řešení, které by mělo fungovat i v dalších prohlížečích (test) – díky:
document.onstorage = spracuj; document.onstoragecommit = spracuj; if (window.addEventListener) { addEventListener('storage',spracuj,false); } else if (window.attachEvent) { attachEvent('onstorage',spracuj); }
Přístup k úložištím
Už jsme si říkali, že WebStorage nabízí dvě úložiště – Local Storage a Session Storage. Tato úložiště jsou implementována jako atributy objektu window
, konkrétně window.localStorage
a window.sessionStorage
. Přistupovat k nim lze i přímo, tedy bez „window“, například takto:
sessionStorage.setItem("username", "John Doe");
nebo
var reloads = localStorage.getItem("reloadCounter");
Můžete se podívat na několik testovacích skriptů: test Session Storage, test Local Storage, výpis hodnot.
Úložiště jako pole
K úložištím je možno přistupovat nejen pomocí metod objektu Storage, ale i jako k polím, kdy jsou metody setItem()
, resp. getItem()
, volány transparentně na pozadí. Výše uvedené příklady můžeme tedy přepsat do podoby:
sessionStorage["username"] = "John Doe"
či
var reloads = localStorage["reloadCounter"];
Storages ale nedefinují iterátor, nemůžeme tudíž k procházení uložených hodnot použít konstrukci for( .. in ..)
. (Lze sice poměrně snadno iterátor doimplementovat, ale přepisování prototypů systémových objektů není ukázka příliš dobrého vychování. – pozn.aut.)
Krátká odbočka k offline aplikacím
Máme AppCache, která udrží soubory naší aplikace v prohlížeči i když je offline. Máme WebStorage, kam můžeme ukládat data. K tomu, abychom mohli vytvořit offline aplikaci, potřebujeme už jen detail: Zjistit, zda je uživatel online nebo offline a podle toho se zařídit. K tomu slouží vlastnost navigator.onLine
, která má hodnotu buď true (=prohlížeč je online), nebo false (=prohlížeč je offline). Kromě toho můžeme využít i obsluhu událostí online
a offline
, které jsou vyvolány u dokumentu v případě, že prohlížeč přejde do režimu online (či do režimu offline). Jednoduchou konstrukcí typu
document.body.addEventListener("online", function () {...}, false);
můžeme tuto událost zachytit, a např. po přechodu do online módu můžeme obsah lokálního úložiště synchronizovat se serverem, můžeme nahrát na server obsah cache apod.
Shrnutí
WebStorages jsou v současné době poměrně přijatelná metoda pro ukládání dat na straně klienta. Ve spojení s minule popsanou AppCache nabízí poměrně slušné možnosti k vytváření webových aplikací, které jsou schopny pracovat i bez připojení (typicky mobilní telefony). V hlavních dnes používaných prohlížečích jsou implementovány, až na událost storage
, u níž je funkčnost nejistá, což ale pravděpodobně ve většině aplikací nebude představovat nijak zásadní problém. Není proto žádný důvod se používání WebStorage ve webových aplikacích, určených primárně pro moderní prohlížeče, bránit.
Doporučené čtení k tématu:
- DiveIntoHTML5 – Local Storage
- Sencha blog
- HTML5 Storage test
- Safari Reference Library – Storages
- Mozilla Hacks – Local Storage
- Mozilla Hacks – Offline web applications
Přehled komentářů