#40 IndexedDBの使い方
ブラウザにはIndexedDBという、インデックス付きテーブルなデータベースが用意されています。 今回はこのIndexedDBの使い方を紹介してみます。
MDNの公式ドキュメントはこちらにあります。
データベースを開く
データベースを開くには、indexedDB.open()
を使います。この関数はコールバックベースなので、次のようにPromise
を返す関数でラップするとよいでしょう。
const openIndexedDB = (name, version, onupgradeneeded) =>
new Promise((resolve, reject) => {
// 開く
const r = indexedDB.open(name, version);
r.onupgradeneeded = (ev) => {
const db = ev.target.result;
onupgradeneeded(db);
};
// IDBDatabase型を結果として返す
r.onsuccess = (ev) => resolve(ev.target.result);
r.onerror = (ev) => reject(ev);
});
onupgradeneeded()
は初回のオープンや、バージョンが変わった時に呼ばれます。オブジェクトストア作成はここで行うとよいでしょう。
オブジェクトストアを作る
IndexedDBでは、テーブルに相当するものとしてオブジェクトストアがあります。データベースの初回オープン時に作成してしまいましょう。
// testというデータベースを開く
const db = await openIndexedDB("test", 1, (db) => {
// オブジェクトストアを作る
db.createObjectStore("myStore", { keyPath: "id" });
});
オブジェクトストアを作るには、createObjectStore()
を呼びます。第1引数にはオブジェクトストア名を指定し、
第2引数には上記のようにキーとなるフィールド名を指定します。
データを追加する
データをオブジェクトストアに追加するには、次のようにput()
を呼びます。このメソッドもコールバックベースになっているので、
Promise
でラップするのがよいでしょう。
const putData = (db, storeName, value) =>
new Promise((resolve, reject) => {
const tr = db.transaction([storeName], "readwrite");
const store = tr.objectStore(storeName);
// ここでデータを追加
const request = store.put(value);
tr.oncomplete = () => resolve();
tr.onerror = (err) => reject(err);
});
put()
の場合、オブジェクトストアに同じキーのデータがあった場合は上書きになります。store.add(value)
もあり、こちらは同じキーのデータがあった場合はエラー(Key already
exists in the object store.)になります。
データを取得する
getAll()
を呼ぶとオブジェクトストアに入っているデータ全部を取得し、
get(key)
を呼ぶとキー指定で1件だけ取得します。
const getAll = (db, storeName) =>
new Promise((resolve, reject) => {
const tr = db.transaction([storeName]);
const store = tr.objectStore(storeName);
// 全件取得
const request = store.getAll();
request.onsuccess = (ev) => resolve(ev.target.result);
request.onerror = (err) => reject(err);
});
キー指定で1件だけ取得するラッパーです。
const getByKey = (db, storeName, key) =>
new Promise((resolve, reject) => {
const tr = db.transaction([storeName]);
const store = tr.objectStore(storeName);
const request = store.get(key);
request.onsuccess = (ev) => resolve(ev.target.result);
request.onerror = (err) => reject(err);
});
まとめ
IndexedDBの基本的な使い方を紹介しました。ブラウザに大量のデータを保存させたい場合に役立つので、使えるようになっておきましょう。