🙆
IndexedDBを活用したページ状態の保存、復元、削除
Webアプリケーションにおいて、ユーザーのアクションや設定に基づきページの状態を保存、復元、または削除することは頻繁に求められる要件となっています。この記事では、そのようなタスクをIndexedDBを利用して実現する方法と、実装時の注意点について解説します。
1. IndexedDBとは?
IndexedDBは、ブラウザ内での大量データの保存を目的とした低レベルAPIです。これはオブジェクトベースのデータベースで、オブジェクトを直接保存することが可能です。
2. ページ状態の保存、復元、削除
以下のコードは、ページのURLをキーとしてデータを保存、読み込み、または削除する手法を示しています。
Javascript:
script.js
const PageState = {
db: null,
init() {
const request = indexedDB.open("myDatabase", 1);
request.onupgradeneeded = (event) => {
this.db = event.target.result;
const objectStore = this.db.createObjectStore("pageState", {
keyPath: "url",
});
};
request.onsuccess = (event) => {
this.db = event.target.result;
};
},
saveState(data) {
const transaction = this.db.transaction(["pageState"], "readwrite");
const objectStore = transaction.objectStore("pageState");
objectStore.put({ url: window.location.href, data });
},
loadState() {
const transaction = this.db.transaction(["pageState"]);
const objectStore = transaction.objectStore("pageState");
const request = objectStore.get(window.location.href);
return new Promise((resolve, reject) => {
request.onsuccess = (event) => {
resolve(request.result ? request.result.data : null);
};
request.onerror = (event) => {
reject(new Error("Data retrieval failed"));
};
});
},
deleteState() {
const transaction = this.db.transaction(["pageState"], "readwrite");
const objectStore = transaction.objectStore("pageState");
const request = objectStore.delete(window.location.href);
return new Promise((resolve, reject) => {
request.onsuccess = (event) => {
resolve(true);
};
request.onerror = (event) => {
reject(new Error("Data deletion failed"));
};
});
},
};
// 初期化
PageState.init();
HTML:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>IndexedDB Sample with URL as Key</title>
</head>
<body>
<div>
<input type="text" id="dataInput" placeholder="Enter some data">
<!-- PageStateオブジェクトを通じて関数を呼び出す -->
<button onclick="PageState.saveState(document.getElementById('dataInput').value)">Save</button>
<button onclick="retrieveData()">Load</button>
<!-- 以下が追加されたdeleteStateメソッドを呼び出すボタンです -->
<button onclick="deleteData()">Delete</button>
</div>
<div id="output"></div>
<script src="script.js"></script>
<script>
// loadStateの返り値を使用してデータを取得
async function retrieveData() {
try {
const data = await PageState.loadState();
document.getElementById('output').innerText = data || "No data found";
} catch (error) {
console.error("Error retrieving data:", error);
}
}
// 以下が追加されたdeleteStateメソッドを呼び出す関数です
async function deleteData() {
try {
await PageState.deleteState();
document.getElementById('output').innerText = "Data deleted successfully";
} catch (error) {
console.error("Error deleting data:", error);
}
}
</script>
</body>
</html>
3. データの保持期間の追加
Webアプリケーションでは、データの保持期間を設定することが求められる場面があります。IndexedDBを使用して、データの保存時に現在の日時を保存し、その日時を基にしてデータの有効期限を判定することができます。
データの保存時に現在の日時を追加:
データを保存する際に、現在の日時も一緒に保存します。
saveState(data) {
const transaction = this.db.transaction(["pageState"], "readwrite");
const objectStore = transaction.objectStore("pageState");
const now = new Date().getTime(); // 現在の日時を取得
objectStore.put({ url: window.location.href, data, timestamp: now });
}
データの読み込み時に日時を確認して古いデータを削除:
データを読み込む際に、保存された日時を確認し、指定した期間を超えている場合はそのデータを削除します。
loadState() {
const transaction = this.db.transaction(["pageState"]);
const objectStore = transaction.objectStore("pageState");
const request = objectStore.get(window.location.href);
return new Promise((resolve, reject) => {
request.onsuccess = (event) => {
const now = new Date().getTime();
const oneDay = 24 * 60 * 60 * 1000; // 24時間をミリ秒で表現
if (request.result && (now - request.result.timestamp) <= oneDay) {
resolve(request.result.data);
} else {
this.deleteState(); // 期間を超えているデータを削除
resolve(null);
}
};
request.onerror = (event) => {
reject(new Error("Data retrieval failed"));
};
});
}
上記の変更を加えることで、データの保持期間を1日とし、それを超えたデータは自動的に削除されるようになります。必要に応じて保持期間を調整することができます。
4. 考慮すべき問題点
- エラーハンドリング: データベースのオープンやデータの操作時のエラーハンドリングは欠かせません。
- データベースのバージョン管理: バージョンが変わった際の適切な処理が必要です。
- 容量制限: IndexedDBの容量制限を超えるとエラーが発生しますので、この制限を意識してください。
- セキュリティ: 機密情報を保存する場合、データの暗号化などのセキュリティ対策が必要です。
- ブラウザの互換性: すべてのブラウザでIndexedDBがサポートされているわけではないため、互換性を確認することが大切です。
5. まとめ
IndexedDBは、ブラウザ内でのデータの効率的な保存、復元、削除を実現する強力なツールです。しかし、その実装には上記のような多くの注意点が伴います。これらの要点をしっかりと把握しながら、ページの状態管理を適切に行うことが求められます。
6. 参考リンク
詳しいコード例や動作デモを確認したい方は、以下のGitHubリポジトリをご参照ください:
Discussion