はじめに
こんにちは!株式会社iimonでフロントエンドエンジニアをしている「みよちゃん」です! 本記事は株式会社iimonアドベントカレンダー15日目です! 弊社では不動産仲介業者向けのサービスを開発しています。 私が所属しているチームでは、chromeの拡張機能を開発しており、IndexeDBを使用する機会が多くあります。 今回は普段使用するIndexedDBについて調べたことを以下にまとめていきたいと思います!
IndexedDB
1. IndexedDBとは
IndexedDBとはブラウザに実装されているデータベースの機能です。ブラウザ内で処理を完結させることができるので、通信が発生せずオフラインの状態でも使用することができます。データベースはRDB(Relational Database)ではなくキーバリューストアです。
2. ブラウザが持つほかのデータ管理機能との違い
ブラウザのデータ管理機能といえば他にも「Cookie」「SessionStorage」「LocalStorage」などがあげられます。これらと比較したIndexedDBの特徴は * 手動で削除するまで残り続ける * ブラウザによるデータの制限なし(ディスクの空き容量により制限あり) * データにはクライアントのみアクセス可能 * 任意のデータ形式を使用できる これらの特徴からIndexedDBは複雑なデータを大量に、かつ長期間保存するのに向いていると言えそうです。
IndexedDBの使い方
1. データベースを開く
const name = 'DB_NAME'; // データベースの名前(文字列)
const version = 1; // バージョン(デフォルトは1)
let openRequest = indexedDB.open(name, version);
openRequest
のイベントには以下の3つがあります。
* success
:データベースの準備ができたことを示します。
* error
:データベースを開くのに失敗したことを示します。
* upgradeneeded
:DBのバージョンが最新でない場合にトリガーされます。
2. オブジェクトストア作成
IndexedDBのオブジェクトストアとは、ほかのデータベースでテーブルやコレクションと呼ばれるものです。DBは複数のオブジェクトストアを持つことができます。
const storeName = 'user'
openRequest.onupgradeneeded = (e) => {
const db = e.target.result;
db.createObjectStore(storeName,{keyPath:'id'}
}
オブジェクトストアの作成、削除はonupgradeneededの中でしか実行できないので注意が必要です。
3. トランザクション
トランザクションの流れは基本的に以下の4ステップです。 1. トランザクションを作成する 1. 操作するために1に対してオブジェクトストアを取得する 1. 2に対してリクエストを実行する 1. リクエストの成功/失敗に応じて必要な処理を実行する
a. アイテムの追加
今回はuser
というオブジェクトストアにiimonkun
というname
をもつオブジェクトを追加してみましょう!
// 1.トランザクションを作成する
const transaction = db.transaction(storeName, 'readwrite');
// 2. トランザクションを操作するためのオブジェクトストアを取得する
const objectStore = transaction.objectStore(storeName);
const iimonkun = {
id: 2,
name:'iimonkun',
age: 4,
}
// 3. リクエストの実行とresponseに応じたハンドリング
const request = store.add(iimonkun);
request.onsuccess = () => {
console.log('created new user');
}
request.onerror = () => {
console.log('error', request.error);
}
今回はadd
を使用してアイテムの追加を行いましたが、put
を使用することもできます。
add
が同じkeyを持つ値が既に存在する場合にリクエストが失敗するのに対し、put
は同じkeyを持つ値が存在する場合に値が置き換えられるという違いがあります。
目的に応じた使い方ができると良いですね!
b. データの取得
ここでは先ほどオブジェクトストアに追加したiimonkun
をname
を使用して取り出してみましょう!
const transaction = db.transaction('user', 'readonly');
const store = transaction.objectStore('user');
const index = store.index('name');
const request = index.get('iimonkun');
request.onsuccess = (e) => {
const data = e.target.result;
console.log('検索結果', data);
};
それではコンソールを確認してみましょう!
成功です!!うまく取り出せていますね!! IndexedDBでは以下のように検索する方法もあります。
getAll()
const request = objectStore.getAll()
request.onsuccess = (e) =>{
// resultには全てのデータが配列で渡される
const result = e.target.result;
}
getAll
では全てのデータを配列で取得することができます。
openCursor()
const transaction = db.transaction('user', 'readonly');
sotre = transaction.objectStore('user')
cursorRequest = sotre.openCursor();
cursorRequest.onsuccess = (e) => {
// この中で反復処理が行われる
const cursor = event.target.result;
if(cursor.age <= 4){
console.log(`${cursor.name} is under 4 years old .`)
}
cursor.continue();
}
cursor
を使用するとストア内のデータに対して反復処理を行うことができます。複数の条件でデータを検索したいときなどに便利かもしれませんね!
c. アイテムの削除
それでは最後にアイテムの削除を行ってみましょう。今回はopenCursorでデータを削除してみます!
const transaction = db.transaction('data', 'readwrite');
const store = transaction.objectStore('data');
const deleteRequest = store.openCursor()
deleteRequest.onsuccess = (e) => {
const cursor = e.target.result;
if(!cursor) return;
if(cursor.value.name === 'iimonKun'){
cursor.delete();
console.log('success to delete')
}
cursor.continue();
}
cursorのname
値がiimonkun
だった時にデータを削除するような処理になています。
それではデータが削除できているか確認してみましょう。
イメージ通り削除されていますね!
これは削除処理に限った話ではありませんが、cursorでループを回す場合cursor.continue
で次のループに移りますが、ループ終了の判定を自身で実装しなければならないので注意が必要です。
おわりに
今回改めてIndexedDBに関して調べたところ、あまり意識していなかった他データ管理機能との違いなど、新しい気づきがありました。今回学習した内容を元にIndexedDBを使用するべきタイミングや、適切なデータの扱い方を意識して業務を行えればと思います!
最後までご覧いただきありがとうございます。 弊社ではエンジニアを募集しております! この記事を見て気になった方、是非一度カジュアルにお話ししましょう! ご応募心よりお待ちしております!!! Wantedly / Green
次回のアドベントカレンダー記事担当は我らがCTO「もりご」さんです! 先日ダーツがかなりの腕前であることが発覚した「もりご」さん、きっとみなさんの心に刺さる記事を書いて下さることでしょう!! 今から楽しみですね!