【ルービックキューブのタイマーを作る】第5回 IndexedDBを使ってみる回
もうシリーズも今回で5回目。今回は、テスト的にIndexedDBを使ってみようと思う。個人的に使ったことがないので。テスト回なのでソースコードは微妙なところが多々ありますが、お許しください。
IndexedDBとは
IndexedDBは、ブラウザ内にデータを保存する機能。永続的保存です。CookieやlocalStorageは、容量の問題で却下。サーバー側のRDBを利用する事も考えたが、複数人で利用する場合にはユーザー管理が必要になるので、いまいち。そこで、IndexedDBを採用することにする。
IndexedDBは利用できる容量が桁違いに多いので問題なく、ブラウザで管理される事によりこちらでユーザー管理を考える必要もない。
基本の使い方は?
さて、IndexedDBはまったく利用したことがないので、そのあたりからお勉強である。
IndexedDB API – Web API | MDNを見て、学ぶ。
const DB_NAME = 'cube';
const DB_VERSION = 3;
const storeName = 'data';
let db;
let objStore;
const request = window.indexedDB.open(DB_NAME, DB_VERSION);
// open失敗
request.onerror = (event) => {
window.alert('データの保存に失敗しました');
};
request.onsuccess = (event) => {
db = event.target.result;
};
request.onupgradeneeded = (event) => {
db = event.target.result;
objStore = db.createObjectStore(storeName, {keyPath: 'name'});
const data = {name:'dataset1', date: 1741489549, scramble: 'B D\' B2 R D2 R D\' B L2 F2 U2 D\' B2 L2 U\' B2 D B2 U\' R', time: 41581};
objStore.add(data);
};
ちょっと正しい使い方かはさておき、データを追加することには成功しました。Chromeのデベロッパーツールで見てみたのがこちら。

配列をそのままつっこんでみる
いろいろドキュメントを眺めてみると、基本的にはKVS的な使い方が一般的なのかなと感じ取れた。
と同時に、某有名サービスでこういう使い方をしているみたいなので、同様にやってみた。キーを指定して全データが入った配列を取得するような使い方だ。
const DB_NAME = 'cube';
const DB_VERSION = 3;
const storeName = 'data';
let db;
let objStore;
const request = window.indexedDB.open(DB_NAME, DB_VERSION);
// open失敗
request.onerror = (event) => {
window.alert('データの保存に失敗しました');
};
request.onsuccess = (event) => {
db = event.target.result;
};
request.onupgradeneeded = (event) => {
db = event.target.result;
objStore = db.createObjectStore(storeName);
const data = [
{
name: 'dataset1',
date: 1741489549,
scramble: 'B D\' B2 R D2 R D\' B L2 F2 U2 D\' B2 L2 U\' B2 D B2 U\' R',
time: 41581
},
{
name: 'dataset1',
date: 1741489549,
scramble: 'B D\' B2 R D2 R D\' B L2 F2 U2 D\' B2 L2 U\' B2 D B2 U\' R',
time: 41581
},
{
name: 'dataset1',
date: 1741489549,
scramble: 'B D\' B2 R D2 R D\' B L2 F2 U2 D\' B2 L2 U\' B2 D B2 U\' R',
time: 41581
}
];
objStore.add(data, 'dataset1');
};
こうすると、データはどうなるか。

無事配列データが入っていますね。こうしておくと、データセットを分けて保存したい場合、キーを変更して保存するということになる。
やっぱり1件ずつデータ登録したい気がする
しかしまぁ・・・本来の目的を考えると、1件ずつ別データとして保存しておくのがきれいな形な気はするので、トライする。
const DB_NAME = 'cube';
const DB_VERSION = 3;
const storeName = 'data';
let db;
let objStore;
const request = indexedDB.open(DB_NAME, DB_VERSION);
// open失敗
request.onerror = (event) => {
window.alert('データの保存に失敗しました');
};
request.onsuccess = (event) => {
db = request.result;
};
request.onupgradeneeded = (event) => {
db = request.result;
objStore = db.createObjectStore(storeName, {keyPath: "id", autoIncrement: true});
const datasetIndex = objStore.createIndex("by_dataset", "dataset");
const data = [
{
dataset: 1,
time: 41581,
scramble: 'B D\' B2 R D2 R D\' B L2 F2 U2 D\' B2 L2 U\' B2 D B2 U\' R',
date: 1741489549,
},
{
dataset: 2,
time: 39581,
scramble: 'B D\' B2 R D2 R D\' B L2 F2 U2 D\' B2 L2 U\' B2 D B2 U\' R',
date: 1741499549,
},
{
dataset: 1,
time: 65581,
scramble: 'B D\' B2 R D2 R D\' B L2 F2 U2 D\' B2 L2 U\' B2 D B2 U\' R',
date: 1741519549,
}
];
objStore.put(data[0]);
objStore.put(data[1]);
objStore.put(data[2]);
};

こうしておいて、dataset=1のみ取得して使うことが出来れば良い。
const DB_NAME = 'cube';
const DB_VERSION = 3;
const storeName = 'data';
let db;
let objStore;
let items = [];
const request = indexedDB.open(DB_NAME, DB_VERSION);
// open失敗
request.onerror = (event) => {
window.alert('データの保存に失敗しました');
};
request.onsuccess = (event) => {
db = request.result;
};
request.onupgradeneeded = (event) => {
db = request.result;
objStore = db.createObjectStore(storeName, {keyPath: "id", autoIncrement: true});
const datasetIndex = objStore.createIndex("by_dataset", "dataset");
const data = [
{
dataset: 1,
time: 41581,
scramble: 'B D\' B2 R D2 R D\' B L2 F2 U2 D\' B2 L2 U\' B2 D B2 U\' R',
date: 1741489549,
},
{
dataset: 2,
time: 39581,
scramble: 'B D\' B2 R D2 R D\' B L2 F2 U2 D\' B2 L2 U\' B2 D B2 U\' R',
date: 1741499549,
},
{
dataset: 1,
time: 65581,
scramble: 'B D\' B2 R D2 R D\' B L2 F2 U2 D\' B2 L2 U\' B2 D B2 U\' R',
date: 1741519549,
}
];
objStore.put(data[0]);
objStore.put(data[1]);
objStore.put(data[2]);
};
document.getElementById('scramble').addEventListener('click', function () {
const tx = db.transaction(storeName, "readonly");
const store = tx.objectStore(storeName);
const index = store.index("by_dataset");
const allResult = index.getAll(1);
allResult.onsuccess = (event) => {
items = event.target.result;
};
});
document.getElementsByTagName('header')[0].addEventListener('click', function () {
console.log(items);
});
ちょっとソースコードはきたないんですが、許してくださいw無事に値は取得できました。なんとか使えそうな気がします。
まとめ
IndexedDBにデータを保存し、取得することが出来ました。使い方には少し癖があるので、やや大変でした。次回は、思考錯誤しながらですが、
今回のソースコード
本日の実装が完了した状態のタグが「v1.0.5」です。今回のファイルはテスト用ファイルなので、次回には削除していると思います。
https://github.com/supilog/cube/tree/v1.0.5
- app/Http/Controllers/CubesController.php
- resources/js/db.js
- resources/views/test01.blade.php