2015/03/26

TypeScriptでIndexedDBの登録・更新・削除・検索をする

IndexedDBは、HTML5で動作するKey-Value型のローカルストレージ。
簡単に言うと、ブラウザを閉じても保存しておきたいデータを格納するための仕組み。

他にもWebStorageやWebSQLなどがある。
今後は、IndexedDBが最も利用されるデータベースになる! ……らしい。

当エントリは、最近個人的に勉強を始めた「TypeScript」でIndexedDBを操作する方法をまとめる。
最後にコンパイルしたJavaScriptも載せておくので、TypeScriptに興味ない人はそちらを参照ください。

開発環境

  • TypeScript 1.4
  • Visual Studio Community 2013
  • InternetExplorer 11 / Google Chrome 41



今回つくるモノ


今回IndexedDBを使うにあたり、以下のサイトを参考にさせていただいた。

▶ Indexed Database API について - へっぽこプログラマーの日記


そして、以下のような感じの超簡易的なレイアウトで、「登録」「更新」「削除」「全削除」「検索」「全検索」を行う。


開発メモ

  • データベース名:library
  • オブジェクトストア名:books
  • インデックス名:index
  • キー項目名:isbn

注意点

今回のサンプルにjQueryを使用している。
VS Community 2013インストール直後だと、jQueryの型定義でアホほどエラーがでる。
そんなときは、TypeScriptのバージョンを1.4にしてください。

▶ TypeScript 1.4 for Visual Studio 2013 拡張機能


ちなみに、jQueryや型定義は、Nugetで「jQuery DifinitelyTyped」とか検索するとでてくる。



データベースの作成


// ベンタープレフィックス(webkit:Chrome、moz:FireFox)
var indexedDB = window.indexedDB;// || window.webkitIndexedDB;

// データベース接続
var db: IDBDatabase = null;
var request = indexedDB.open('library', 1);

// 接続成功(初回 or DBのバージョンが変わったとき)
request.onupgradeneeded = (event) => {
    db = (<IDBRequest>event.target).result;

    // オブジェクトストア作成(インデックスのキーとして'isbn'を指定)
    var store = db.createObjectStore('books', { keyPath: 'isbn' });
    // インデックスの作成
    store.createIndex('index', 'isbn', false);
};

// 接続成功(すでにDBが存在する場合)
request.onsuccess = (event) => {
    db = (<IDBRequest>event.target).result;
};

request.onerror = (event) => {
    console.log(event.message);
};

ベンタープレフィックス対応のところで、window.webkitIndexedDBを使用すると、Property 'webkitIndexedDB' does not exist on type 'Window'.というエラーが発生するため、コメントアウトしている。(コメントアウトした状態でも、ChromeでIndexedDB使えたけど…)

onupgradeneededonsuccessのコールバックメソッド内で、JavaScriptならthis.resultevent.target.resultと書けるが、TypeScriptの場合はそのまま書くとエラーになってしまうため、適切な型にキャストしている。


型推論を使っているので、一見どんな型かわからないと思うので、補足しておく。
TypeScriptを使うときは、型に注意しないとエラーになっちゃうので!

変数名
indexedDBIDBFactory
dbIDBDatabase
requestIDBOpenDBRequest
storeIDBObjectStore



データ登録・更新


var trans = db.transaction('books', 'readwrite');
var store = trans.objectStore('books');

// 登録対象のデータ(BookInfoはInterfaceで定義)
var bookInfo: BookInfo = {
    name: $('#name').val(),
    description: $('#description').val(),
    author: $('#author').val(),
    isbn: $('#isbn').val()
};

// データ登録・更新
var request = store.put(bookInfo);

request.onsuccess = (event) => {
    console.log('登録成功');
};

request.onerror = (event) => {
    console.log('登録失敗:' + event.message);
};

トランザクションを開始し、データを登録・更新する処理。

13行目のstore.put(bookInfo)>だが、
IDBObjectStore.put()を使うと、キーが存在する場合は更新、存在しない場合は登録と自動的に判断してくれる。
IDBObjectStore.add()もあるが、こちらはキーが存在すると重複エラー、存在しない場合は登録となる。

似ているようでちょっと違うので要注意!


一応型も。。。
変数名
transIDBTransaction
storeIDBObjectStore
requestIDBRequest
bookInfoユーザ定義(BookInfo)



データ検索


var key = $('#isbn').val();

var trans = db.transaction('books', 'readonly');
var store = trans.objectStore('books');

// データ取得
var request = store.get(key);

request.onsuccess = (event) => {
    var result = <BookInfo>(<IDBRequest>event.target).result;
    if (result) {
        render(result);
    } else {
        console.log('対象データは存在しません。');
    }
};

1行目の「key」が検索キーをテキストボックスから取得する。
この検索キーは、オブジェクトストア作成時に「keyPath」として指定したモノ。

7行目の「store.get(key)」でデータを取得する。
データが0件だった場合も、onsuccessコールバックが呼ばれるので注意。

12行目は、取得したデータ(result:BookInfo)を画面表示用のRenderメソッドに渡している。

型については、「データ登録・更新」と同じなので省略。



全データ取得


var trans = db.transaction('books', 'readonly');
var store = trans.objectStore('books');

// 全データ取得
var request = store.openCursor();

request.onsuccess = (event) => {
    var cursor = <IDBCursorWithValue>(<IDBRequest>event.target).result;

    if (cursor) {
        render(cursor.value);
        cursor.continue();
    }
};

「データ検索」と違い、store.openCursorを使うことで一度に複数のデータを取得することができる。

openCursor(optionalKeyRange, optionalDirection)の第1引数にIDBKeyRangeを渡すことで「1件目~10件目までを取得」といった範囲指定も可能。第2引数に'NEXT'や’PREV'などを渡すことで、取得する順番も指定できる。

データ取得後の処理は、request.onsuccessが何度も呼ばれるイメージ。

transやstoreなどは、「データ登録・更新」と同じなので省略。
変数名
cursorIDBCursorWithValue



データ削除


var key = $('#isbn').val();

var trans = db.transaction('books', 'readwrite');
var store = trans.objectStore('books');

// データ削除
var request = store.delete(key);

request.onsuccess = (event) => {
    console.log('削除成功');
};

request.onerror = (event) => {
    console.log('削除失敗:' + event.message);
};
「データ検索」に似ている。
7行目の「store.delete(key)」で、データを削除する。

この削除するときのキーは、オブジェクトストア作成時に「keyPath」として指定したモノ。

型は他のと同じなので省略。



全データ削除


var trans = db.transaction('books', 'readwrite');
var store = trans.objectStore('books');

// 全データ削除
var request = store.clear();

request.onsuccess = (event) => {
    console.log('全データ削除成功');
};

request.onerror = (event) => {
    console.log('全データ削除失敗:' + event.message);
};

「データ削除」とほぼ同じ。
違うところは、5行目のstore.clear()これでオブジェクトストア内のデータがすべて消える。
※オブジェクトストアは削除されない。

型は(以下略



ソースコード(HTML+TypeScript+JavaScript)




参考サイト


わからないところは、MDNで型(IDBObjectStoreなど)を検索し、「Example」を入ればだいたいわかるのでオススメ。



以上

written by @bc_rikko

0 件のコメント :

コメントを投稿