niedziela, 24 lutego 2013

[HTML|JS|CSS] HTML5: IndexedDb

Ciekawym trendem, jaki można zaobserwować w standardzie HTML5 jest możliwość składowania coraz większej ilości danych po stronie klienta. Przestarzałe ciasteczka zastępowane są przez znacznie lepszy mechanizm localStorage. To jednak nie wszystko. Pojawia się także możliwość składowania danych w dokumentowej bazie IndexedDb. Podobnie jak w WebStorage, dane zapisywane są dla danej strony internetowej i tylko z jej poziomu mogą być odczytane. Tym razem możemy jednak składować całe obiekty JavaScriptowe, a nie tylko ciągi znaków. Co więcej, zgodnie z dokumentacją IndexedDb, pojemność takiej bazy praktycznie ograniczona jest jedynie miejscem na dysku. Same zapytania wykonywane są w sposób asynchroniczny, programista zatem musi ich wynik obsłużyć w callbackach.

Pracę z indexedDb, technologią mocno eksperymentalną, nad którą prace cały czas trwają, warto rozpocząć od  przypisania sobie dla wygody każdej z możliwych implementacji bazy do jednej zmiennej.

window.indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;

Jak widać ostatnim silnikiem przeglądarek, który nie wspiera indexedDb jest Presto, na którym tworzona była Opera (obecnie opera ma także być tworzona w oparciu o webkit, więc problem znika dla nowszych wersji).

Zapisywanie obiektów do bazy odbywa się poprzez odpowiednie callbacki.

$("#store").click(function(){
 var value = $("#msg").val();
 var request = indexedDB.open("MyDb", 1); //1
 request.onsuccess = function (evt) {
  db = request.result;
  var transaction = db.transaction("messages", "readwrite"); //2
  var objectStore = transaction.objectStore("messages"); //3                   
  var req = objectStore.add({ date: new Date().toLocaleString(), message: value });
  req.onsuccess = function (evt) {
   console.log('successfully saved');
  };
 };
 request.onerror = function (evt) {
  console.dir(evt);
 };

 request.onupgradeneeded = function (evt) {
  //...
 };
});

Ważne są trzy linie:
  1. Otwieramy bazę danych o nazwie MyDb, opcjonalnie jako drugi parametr podajemy wersję schematu bazy, do której chcemy się łączyć
  2. Pierwszy argument może być także tablicą i jest listą kontenerów, na których będzie wykonywana transakcja
  3. Żeby dodać obiekt do pojedynczego kontenera potrzebujemy obiekt typu objectStore, o nazwie messages
Powyższy kod sprawdza się pod warunkiem, że mamy już utworzoną bazę i kontener, w przeciwnym wypadku wywołana zostanie funkcja onupgradeneeded. 

request.onupgradeneeded = function (evt) {
 var objectStore = evt.currentTarget.result.createObjectStore("messages", 
                             { keyPath: "id", autoIncrement: true 
                         });

    objectStore.createIndex("date", "date", { unique: false });
    objectStore.createIndex("message", "message", { unique: false });
};

Tworzymy objectStore o nazwie messages, posiadający unikalny autoinkrementujący się identyfikator. Dodatkowo, na potrzeby wyszukiwania, można utworzyć dwa indeksy.

Odczyt danych

Podczas odczytu wykorzystuje się indeksy, zwracające wartość i wskaźnik na następny element z kolekcji.

$("#restore").click(function(){
 var request = indexedDB.open("MyDb");
 request.onsuccess = function(evt){
  var db = request.result;
  var transaction = db.transaction("messages");
  var objectStore = transaction.objectStore("messages");
  var req = objectStore.openCursor();
  req.onsuccess = function(evt){
   var cursor = evt.target.result;
   if(cursor){
    var obj = cursor.value;
    var li = $("<li>");
    li.html(obj.date + ", " + obj.message);
    items.append(li);
    cursor.continue();
   }
  }
 }
});

Usuwanie

Korzystając z unikalnych indeksów, usuwanie staje się bardzo proste.Na przykład dla elementu o indeksie 1


$("#removeFirst").click(function(){
 var request = indexedDB.open("MyDb");
 request.onsuccess = function (evt) {
  db = request.result;
  var req = db.transaction(["messages"], "readwrite")
            .objectStore("messages").delete(1);
        }
});

Na koniec warto wspomnieć o tym, jak wygodnie można oglądać stan bazy w przeglądarce Google Chrome, w zakładce Resources.

Brak komentarzy:

Prześlij komentarz