NOVINKA: Staň se datovým analytikem od 0 Kč a získej jistotu práce, lepší plat a nové kariérní možnosti. Více informací:

Lekce 6 - Datová úložiště v JavaScriptu

V předešlém cvičení, Řešené úlohy k 4.-5. lekci OOP v JavaScriptu, jsme si procvičili nabyté zkušenosti z předchozích lekcí.

V dnešním tutoriálu objektově orientovaného programování v JavaScriptu si představíme způsoby, jakými můžeme v JavaScriptu ukládat data tak, abychom je při obnovení stránky hned zas neztratili. Sice tím od samotného OOP lehce odbočíme, je však důležité se i v této problematice orientovat. Znalosti z dnešní lekce se nám mimo jiné budou hodit při tvorbě našeho diáře.

localStorage v JavaScriptu - Objektově orientované programování v JavaScriptu

Příprava projektu

Pro účely zkoušení probírané látky si založíme jednoduchou HTML stránku index.html a ve složce js/ jeden skript obsluha.js, do kterého budeme psát náš kód. V souboru index.html budeme mít pouze základní HTML strukturu a nalinkovaný skript obsluha.js:

<!DOCTYPE html>
<html lang="cs-cz">
<head>
    <meta charset="UTF-8">
    <title>Úložiště</title>
</head>
<body>
    <script src="js/obsluha.js"></script>
</body>
</html>

Web storage

Web storage, také známý jako DOM Storage, představuje dva hlavní mechanismy pro ukládání dat v prohlížeči: localStorage a sessionStorage. Tyto mechanismy poskytují možnost uchovávat data tak, aby byla dostupná i po obnovení stránky nebo případně i jejím úplném zavření.

localStorage

localStorage je úložiště v internetovém prohlížeči uživatele (proto local), do něhož se mohou ukládat data v textovém řetězci, ke kterým můžeme později přistupovat. K dispozici máme pro naši aplikaci typicky 10 MB prostoru (tento limit se může lišit v závislosti na konkrétním prohlížeči a platformě), což je pro texty opravdu hodně :) Možnost ukládat jen text je poměrně omezující, ale stejně je localStorage kvůli své jednoduchosti nejoblíbenějším úložištěm dat, o která nechceme po obnovení nebo zavření stránky přijít.

Práce s localStorage

S localStorage se pracuje velmi jednoduše voláním metod na objektu localStorage, který máme přístupný odkudkoliv. Postupně si představíme ty nejdůležitější.

Metoda setItem()

K uložení nějakého řetězce pod textový klíč použijeme metodu setItem(). Zkusme si pod klíč "jmeno" uložit řetězec "Karel":

localStorage.setItem("jmeno", "Karel");

Stránku se skriptem nyní otevřeme v prohlížeči, kód následně smažeme a stránku zas obnovíme. Tím jsme si jistí, že Karla již nikde v kódu nemáme, ale je uložený v úložišti. To si ihned ověříme.

Metoda getItem()

Analogicky pro přečtení hodnoty pod klíčem použijeme metodu getItem(). Vypišme si, co je uloženo pod dříve použitým klíčem "jmeno":

document.write(localStorage.getItem("jmeno"));

Výsledek:

Tvoje stránka
localhost

Vidíme, že se Karel z localStorage opravdu načetl.

Přestože localStorage v našem příkladu obsahuje položky, které jsme si do něj uložili, neměli bychom na to vždy spoléhat. V praxi může jakýkoli uživatel k úložišti přistoupit a měnit jej pomocí nástrojů pro vývojáře.

Metoda removeItem()

Asi nás nepřekvapí, že řetězec pod nějakým klíčem můžeme z úložiště i vymazat. Uděláme to metodou removeItem():

localStorage.removeItem("jmeno");
Metoda clear()

Úložiště můžeme kompletně vyprázdnit od všech klíčů a dat pod nimi metodou clear():

localStorage.clear();
Vlastnost length

Počet položek v localStorage získáme pomocí vlastnosti length:

document.write("Uloženo " + localStorage.length + " položek");

Výsledek:

Tvoje stránka
localhost
Metoda key()

Možná nás napadlo, jak zjistíme, co vše je v localStorage uloženo, nebo jak s položkami v úložišti pracovat hromadně. Poslední chybějící metoda je proto key(n), kde n je index – pořadové číslo klíče, který chceme vrátit. V kombinaci s vlastností length tak dokážeme například vypsat všechny klíče v úložišti a hodnoty pod nimi uložené.

Udělejme si poslední ukázku, čímž opravdu vyčerpáme možnosti, které localStorage nabízí:

for (let i = 0; i < localStorage.length; i++) {
    const klic = localStorage.key(i);
    document.write(klic + ": " + localStorage.getItem(klic) + "<br>");
}

Pokud jsme si Karla z localStorage ještě nesmazali, vypíše se nám spolu s jeho klíčem:

Tvoje stránka
localhost

Pořadí klíčů může být v každém prohlížeči jiné, a proto by na něm naše aplikace neměla záviset. Neměli bychom tedy například předpokládat, že prvně přidaná hodnota bude vždy pod klíčem 0.

Uložení více hodnot pod jeden klíč

Naskýtá se otázka, jakým způsobem je možné uložit například pole hodnot nebo objekt pod jeden klíč úložiště. Pokud bychom související hodnoty neseskupovali pod jeden klíč, byl by v úložišti opravdu nepořádek. Jen si zkusme představit, jak bychom tam uložili dva uživatele. V takovém případě si proto celý objekt převedeme na textový řetězec a uložíme tento řetězec. Převod objektu na textový řetězec se v JavaScriptu řeší pomocí formátu JSON. To se naučíme v lekci Formát JSON a potom si to i prakticky vyzkoušíme na našem OOP diáři.

sessionStorage

Kromě localStorage existuje také úložiště sessionStorage. To funguje úplně stejně, ale liší se v kontextu, v kterém jsou data uložena. Rozdíly jsou tři:

  • Data v sessionStorage jsou unikátní pro každou záložku prohlížeče. Když si naopak otevřeme tu samou stránku používající localStorage ve více záložkách, budou všechny záložky používat to samé úložiště s těmi stejnými daty.
  • Data budou ztracena ve chvíli zavření záložky. Naopak data v localStorage v prohlížeči zůstávají.
  • Proč tedy sessionStorage používat, když se se zavřením stránky stejně smaže? To už bychom přeci mohli data uložit jen do proměnných jako doposud... sessionStorage podobně jako cookies zůstává netknuté při obnovení stránky nebo při přechodu na jinou stránku v té samé doméně.

Cookies

O "sušenkách" jistě každý slyšel, minimálně v souvislosti s Evropskou Unií a její nechvalně proslulou cookie hláškou:

EU cookie hláška - Objektově orientované programování v JavaScriptu

Cookies mají hned několik využití, nejdůležitější jsou tyto tři:

  • Uložení dat v prohlížeči – Cookies byly dlouhou dobu jediným způsobem, jak si v prohlížeči něco uložit, aniž by se to při obnovení stránky ztratilo. Takto jsme si mohli uložit například, že jsme na stránce již vykřížkovali cookie hlášku ;-) K tomuto účelu se v dnešní době používá zmiňované úložiště localStorage. Tam se hodnoty z úložiště jednodušeji získávají a navíc nezpomalují komunikaci se serverem, protože se neposílají s každým požadavkem.
  • Přihlašování uživatelů – Jelikož prohlížeč spolu s požadavkem na server odesílá serveru i všechny cookies v dané relaci, realizuje se přes ně přihlášení uživatele na serveru. Jinými slovy, hodnotu cookies uživatele můžeme číst na serveru v jazycích jako je PHP nebo C# .NET. Toto využití je potom popsáno v příslušných serverových kurzech.
  • Získání informací o uživateli – Do cookies si Google například uloží, že jsme na něm hledali boty. Google reklamy na jiných stránkách si poté načtou z cookies to, co nás zajímá, a dané zboží nám nabízí. Podobně funguje i Google Analytics, jejichž cookie je snad na každé internetové stránce.

V klientském JavaScriptu tedy již pro používání cookies není příliš dobrý důvod. Pro úplnost si práci s nimi ale stejně ukážeme, učit se ji ale nemusíte.

Cookies se v JavaScriptu nastavují pomocí vlastnosti document.cookie, která obsahuje všechny cookies. Při přiřazení nové hodnoty se nepřepíšou všechny existující cookies, ale přidá se pouze jedna nová.

Cookie se zapisuje jako řetězec s několika částmi oddělenými středníky:

document.cookie = "eu_hlaska_zavrena=1; expires=Sun, 29 Mar 2020 22:00:00 GMT; path=/";

Cookie zadáváme:

  • Název a hodnotu.
  • Datum expirace – Pokud vynecháme, cookie platí do zavření záložky prohlížeče. Pokud nastavíme do minulosti, cookie se ihned odstraní.
  • Cestu – Určuje, kde všude na webu bude cookie platit. Nejčastěji se nastavuje na celou doménu pomocí hodnoty /.

Krkolomné vytváření cookie přímo svádí k napsání funkce. Její kód by byl následující:

function vytvorCookie(nazev, hodnota, expirace = null) {
    const casExpirace = expirace ? `expires=${expirace.toGMTString()};` : '';
    document.cookie = `${nazev}=${hodnota}; ${casExpirace} path=/`;
}

vytvorCookie('eu_hlaska_zavrena', 1, new Date(2030, 2, 30));

Ani načtení cookie není příliš intuitivní. Musíme si totiž nejprve načíst všechny cookies v daném dokumentu, což je dlouhý textový řetězec, ve kterém jsou všechny cookies dané stránky oddělené středníky. Je tam pouze název a hodnota, datum expirace si vnitřně řeší prohlížeč.

Řetězec document.cookie vypadá například takto:

_ga=GA1.2.1621812384.1525606041; __gads=ID=fdbec79e49891ee3:T=1525606041:S=ALNI_MYNHHGQJ65wZIjdzOc60pQanykM8w; __qca=P0-718587983-1559900791988; _gid=GA1.2.2042156113.1583272955; _gat=1; eu_hlaska_zavrena=1"

Nyní je na nás, abychom si z něj hodnotu eu_hlaska_zavrena vypreparovali. Samozřejmě musíme počítat i s tím, že daná cookie vůbec neexistuje! Funkce pro čtení cookies by vypadala takto:

function najdiCookie(nazev) {
    const cookies = document.cookie.split(';')
    for (const cookie of cookies) {
        hodnoty = cookie.split('=');
        if (nazev == hodnoty[0].trim())
            return hodnoty[1].trim();
    }
    return null;
}

document.write(najdiCookie('eu_hlaska_zavrena'));

Zkusme si v prohlížeči, že to opravdu funguje:

Tvoje stránka
localhost

Jak již bylo řečeno, všechny hodnoty všech cookie se odesílají na server v hlavičce HTTP požadavku při každém načtení každé stránky. Proto je používejme jen pokud nemůžeme použít localStorage

Cookie nastavená ze serveru může mít nastavenou vlastnost HttpOnly, čímž ji z klientského JavaScriptu nemůžeme načíst. Toto je základní bezpečnostní opatření, které by mělo být nastaveno při používání cookies k autentizaci uživatelů na serveru. Z klientského JavaScriptu tato vlastnost pochopitelně cookies nastavit nelze :)

Odstranění cookie je stejné jako její vytvoření. Pouze nastavíme její expiraci do minulosti, což povede k jejímu odstranění. Jako hodnotu můžeme uvést cokoli.

IndexedDb

Posledním standardním úložištěm, které můžeme v JavaScriptu používat, je IndexedDB. Jak název napovídá, nejedná se již o pouhé úložiště, kam ukládáme data pod nějakými klíči. Jde o plnohodnotnou databázi s tabulkami a indexy, z čehož také vznikl její název. Ukládáme tedy strukturovaná data. Databázové indexy nám umožňují v databázi vyhledávat řádově rychleji a jsme schopní s daty přímo pracovat, aniž bychom je museli převádět z/do textových řetězců, jako je tomu u localStorage. IndexedDB navíc podporuje transakce a další standardní databázové mechanismy, které nám zajistí datovou integritu (že data nejsou uložena špatně, třeba proto, že v aplikaci došlo k chybě, jednoduše se uloží buď vše, nebo nic). V neposlední řadě podporuje rovněž ukládání souborů.

Databáze je takzvaná NoSQL. To znamená, že s ní nekomunikujeme jazykem SQL, jako to u databází bývá zvykem, ale voláním metod na databázových objektech. To je někdy trochu krkolomné, a proto pro ni vzniklo hned několik nástaveb.

IndexedDB je vhodná pro větší aplikace se složitější datovou strukturou a větším množstvím dat. Její používání převyšuje úroveň OOP kurzu a vydalo by na samostatný kurz, proto se s ní zde zabývat nebudeme.

IndexedDB bychom neměli zaměňovat s WebQL, což je jiná nestandardní da­tabáze, která není podporována všemi prohlížeči.

V následujícím kvízu, Kvíz - Datové typy a datová úložiště v JavaScriptu, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.


 

Předchozí článek
Řešené úlohy k 4.-5. lekci OOP v JavaScriptu
Všechny články v sekci
Objektově orientované programování v JavaScriptu
Přeskočit článek
(nedoporučujeme)
Kvíz - Datové typy a datová úložiště v JavaScriptu
Článek pro vás napsal David Hartinger
Avatar
Uživatelské hodnocení:
287 hlasů
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David se informační technologie naučil na Unicorn University - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity