Każdy z nas ma skłonności do chomikowania. Zbieramy wszystko co można sobie wyobrazić: widokówki, znaczki, cukry, pudełka, itd. I nie jest to bez znaczenia, bo zawsze lepiej mieć coś pod ręką na tzw. wszelki wypadek niż drapać się w głowę zastanawiając się skąd wziąć, jeśli zajdzie nagła potrzeba. Jest to po prostu szybsze i ekonomiczniejsze. I tą zasadą warto się kierować również przy programowaniu, dlatego stworzymy dziś prosty cache do przechowywania wartości.
Pudełko pełne wartości.
Będziemy potrzebować pojemnika, w którym pod danym kluczem można będzie zapisać wartość, a podając klucz odczytać wartość jeśli istnieje. Wykorzystamy obiekt localStorage. W tej chwili można by się zatrzymać i zapytać po co cache, skoro właśnie localStorage może pełnić (pełni?) taką funkcję. Dostarcza metody getItem i setItem, więc wystarczy w razie potrzeby zapisywać i odczytywać dane.
Spróbujmy więc zapisać obiekt jako wartość:
localStorage.setItem("klucz", { 0: "abc", 1: "def" });
console.log(localStorage.getItem("klucz"));
Co otrzymasz? [object Object] - nie obiekt, lecz string, ponieważ metoda setItem wywołuje na przekazanej wartości (tu obiekcie) metodę toString. Zapisany obiekt został więc bezpowrotnie utracony. Można powiedzieć: co za cacheana!
Nie chcę Cię stracić!
Jak przechowywać obiekty w localStorage? Z pomocą przyjdzie nam obiekt JSON i jego metody: stringify oraz parse, dzięki którym bez zbędnego wysiłku upakujemy wartości w pudełku, a te nie wylecą dnem. Metoda stringify zamienia obiekt na postać tekstową JSON (to nie jest toString), a metoda parse wykonuje operację odwrotną. Nasz przykład wyglądałby tak:
localStorage.setItem("klucz", JSON.stringify({ 0: "abc", 1: "def" }));
console.log(JSON.parse(localStorage.getItem("klucz")));
Tym razem otrzymamy {0: "abc", 1: "def"}.
Czas to cache!
Znów można powiedzieć: no to skrypt do cache załatwiony! Nie całkiem, bo chcemy mieć również możliwośc ustalania czasu życia naszej wartości, czyli przez jaki czas możemy uznać ją za prawidłową kiedy pobieramy ją z cache. Wraz z wartością będziemy zapisywać więc znacznik czasowy, który powie o momencie nieważności wartości. Ponieważ w localStorage nie można zapisać dwóch wartości pod jednym kluczem, to wartość i znacznik czasowy przechowamy w jednym obiekcie: {value: wartosc, expirationDate: do_kiedy_wazna}.
No dobra, to czas aby pokazać skrypt:
class Hamster {
constructor() {
this.storage = localStorage;
}
getItem(key) {
/* jeśli wartość istnieje */
if (this.storage.getItem(key)) {
/* odczytujemy ją i parsujemy
String->Object
*/
const item = JSON.parse(this.storage.getItem(key));
/* Jeśli data ważności jest teraźniesza
lub późniejsza to zwracamy wartość,
jeśli nie to usuwamy wartość i zwracamy
false
*/
if (item.expirationDate >= Date.now()) {
return item.value;
} else {
this.storage.removeItem(key);
}
}
return false;
}
putItem(key, value, lifetime = 60) {
/* czy klucz i wartość są zdefiniowane
i niepuste,
jeśli tak, to zapisujemy pod danym kluczem
obiekt złożony z wartości
oraz daty ważności jako string
*/
if (key && value) {
this.storage.setItem(
key,
JSON.stringify({
value: value,
expirationDate: Date.now() + lifetime
})
);
}
}
}
/* użycie */
const hamster = new Hamster();
let found;
/* zapisujemy obiekt wraz z URL */
hamster.putItem("/szukaj.php?fraza=Czer", {
0: "ul. Czerwona 2",
1: "ul. Czerniakowska 3"
});
/* odczytujemy wartość spod URL */
found = hamster.getItem("/szukaj.php?fraza=Czer");
console.log(found);
/* tu zapis i odczyt "płaskiej" wartości */
hamster.putItem("/index.php", "Jakiś tekst");
found = cache.getItem("/index.php");
console.log(found);
Po co taki skrypt? Myślę, że przyda się bardzo przy zapytaniach Ajaxowych gdzie często wysyłamy żądania, np. funkcjonalności autocomplete. Kluczem będzie oczywiście URL. Zanim wyślemy kolejne żądanie, sprawdzamy czy w cache istnieje wartość pod danym URL (kluczem), jeśli tak, to zwracamy ją, a zapytania nie musimy wysyłać. Możemy również przechowywać wyniki skomplikowanych obliczeń, których nie chcemy lub nie musimy wykonywać ponownie.
Powodzenia w zbieractwie (wartości!). Do przeczytania w kolejnym wpisie.
Przydatne linki:
Metoda setItem obiektu localStorage
Metoda getItem obiektu localStorage
Metoda parse obiektu JSON
Metoda stringify obiektu JSON