簡単に言うと、ブラウザを閉じても保存しておきたいデータを格納するための仕組み。
他にも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使えたけど…)onupgradeneeded
、onsuccess
のコールバックメソッド内で、JavaScriptならthis.result
やevent.target.result
と書けるが、TypeScriptの場合はそのまま書くとエラーになってしまうため、適切な型にキャストしている。型推論を使っているので、一見どんな型かわからないと思うので、補足しておく。
TypeScriptを使うときは、型に注意しないとエラーになっちゃうので!
変数名 | 型 |
---|---|
indexedDB | IDBFactory |
db | IDBDatabase |
request | IDBOpenDBRequest |
store | IDBObjectStore |
データ登録・更新
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()
もあるが、こちらはキーが存在すると重複エラー、存在しない場合は登録となる。似ているようでちょっと違うので要注意!
一応型も。。。
変数名 | 型 |
---|---|
trans | IDBTransaction |
store | IDBObjectStore |
request | IDBRequest |
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などは、「データ登録・更新」と同じなので省略。
変数名 | 型 |
---|---|
cursor | IDBCursorWithValue |
データ削除
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$(function () { | |
var indexedDB = window.indexedDB; | |
var db = null; | |
var request = indexedDB.open('library', 1); | |
request.onupgradeneeded = function (event) { | |
db = event.target.result; | |
var store = db.createObjectStore('books', { keyPath: 'isbn' }); | |
store.createIndex('index', 'isbn', false); | |
}; | |
request.onsuccess = function (event) { | |
db = event.target.result; | |
}; | |
request.onerror = function (event) { | |
console.log(event.message); | |
}; | |
$('#regist').click(function () { | |
var trans = db.transaction('books', 'readwrite'); | |
var store = trans.objectStore('books'); | |
var bookInfo = { | |
name: $('#name').val(), | |
description: $('#description').val(), | |
author: $('#author').val(), | |
isbn: $('#isbn').val() | |
}; | |
var request = store.put(bookInfo); | |
request.onsuccess = function (event) { | |
console.log('登録成功'); | |
}; | |
request.onerror = function (event) { | |
console.log('登録失敗:' + event.message); | |
}; | |
}); | |
$('#search').click(function () { | |
clear(); | |
var key = $('#isbn').val(); | |
var trans = db.transaction('books', 'readonly'); | |
var store = trans.objectStore('books'); | |
var request = store.get(key); | |
request.onsuccess = function (event) { | |
var result = event.target.result; | |
if (result) { | |
render(result); | |
} | |
else { | |
console.log('対象データは存在しません。'); | |
} | |
}; | |
}); | |
$('#all-search').click(function () { | |
clear(); | |
var trans = db.transaction('books', 'readonly'); | |
var store = trans.objectStore('books'); | |
var request = store.openCursor(); | |
request.onsuccess = function (event) { | |
var cursor = event.target.result; | |
if (cursor) { | |
render(cursor.value); | |
cursor.continue(); | |
} | |
}; | |
}); | |
var render = function (bookInfo) { | |
var tr = $('<tr>').append('<td>' + bookInfo.name + '</td>' + '<td>' + bookInfo.description + '</td>' + '<td>' + bookInfo.author + '</td>' + '<td>' + bookInfo.isbn + '</td>'); | |
$('#lists > tbody').append(tr); | |
}; | |
var clear = function () { | |
$('#lists > tbody > tr').remove(); | |
}; | |
$('#delete').click(function () { | |
var key = $('#isbn').val(); | |
var trans = db.transaction('books', 'readwrite'); | |
var store = trans.objectStore('books'); | |
var request = store.delete(key); | |
request.onsuccess = function (event) { | |
console.log('削除成功'); | |
}; | |
request.onerror = function (event) { | |
console.log('削除失敗:' + event.message); | |
}; | |
}); | |
$('#all-delete').click(function () { | |
var trans = db.transaction('books', 'readwrite'); | |
var store = trans.objectStore('books'); | |
var request = store.clear(); | |
request.onsuccess = function (event) { | |
console.log('全データ削除成功'); | |
}; | |
request.onerror = function (event) { | |
console.log('全データ削除失敗:' + event.message); | |
}; | |
}); | |
}); | |
//# sourceMappingURL=app.js.map |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <reference path="scripts/typings/jquery/jquery.d.ts" /> | |
// データベースに登録するオブジェクトの型 | |
interface BookInfo { | |
name: string; | |
description: string; | |
author: string; | |
isbn: number; | |
} | |
$(() => { | |
// ベンタープレフィックス(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); | |
}; | |
// データ登録・更新 | |
$('#regist').click(() => { | |
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); | |
}; | |
}); | |
// データ検索 | |
$('#search').click(() => { | |
clear(); | |
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('対象データは存在しません。'); | |
} | |
}; | |
}); | |
// 全データ検索 | |
$('#all-search').click(() => { | |
clear(); | |
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(); | |
} | |
}; | |
}); | |
// 画面表示 | |
var render = (bookInfo: BookInfo) => { | |
var tr = $('<tr>').append( | |
'<td>' + bookInfo.name + '</td>' + | |
'<td>' + bookInfo.description + '</td>' + | |
'<td>' + bookInfo.author + '</td>' + | |
'<td>' + bookInfo.isbn + '</td>' | |
); | |
$('#lists > tbody').append(tr); | |
}; | |
// 画面クリア | |
var clear = () => { | |
$('#lists > tbody > tr').remove(); | |
}; | |
// データ削除 | |
$('#delete').click(() => { | |
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); | |
}; | |
}); | |
// 全データ削除 | |
$('#all-delete').click(() => { | |
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); | |
}; | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="ja"> | |
<head> | |
<meta charset="utf-8" /> | |
<title>Indexed Database API</title> | |
</head> | |
<body> | |
<h1>IndexedDB Sample</h1> | |
ISBN(*):<input type="text" id="isbn" /><br /> | |
名前: <input type="text" id="name" /><br /> | |
詳細:<input type="text" id="description" /><br /> | |
著者:<input type="text" id="author" /><br /> | |
<button type="button" id="regist">登録</button> | |
<button type="button" id="search">検索</button> | |
<button type="button" id="all-search">全検索</button> | |
<button type="button" id="delete">削除</button> | |
<button type="button" id="all-delete">全削除</button> | |
<hr /> | |
<table id="lists" border="1"> | |
<thead> | |
<tr> | |
<th>名前</th> | |
<th>詳細</th> | |
<th>著者</th> | |
<th>ISBN</th> | |
</tr> | |
</thead> | |
<tbody></tbody> | |
</table> | |
<script src="Scripts/jquery-2.1.3.min.js"></script> | |
<script src="app.js"></script> | |
</body> | |
</html> |
参考サイト
わからないところは、MDNで型(IDBObjectStoreなど)を検索し、「Example」を入ればだいたいわかるのでオススメ。
以上
written by @bc_rikko
0 件のコメント :
コメントを投稿