以前、以下の記事でカーソルを使って「オブジェクトストア」に登録された全てのデータを取得する方法について説明しましたが、 カーソル処理の中と、全てのデータを取得した後の処理をどうするのかには触れていませんでした。
⇒JavaScript IndexedDB の使い方5(カーソル処理)
全データ取得関数 getAllData の中で直接データ処理を記述してもいいのですが、 汎用性を持たせるために、カーソル処理用と全データ取得後の関数を引数として渡し、それぞれの処理で実行する様に変更してみます。
■全データ取得関数にカーソル処理用と全データ取得後の関数を引数として渡す
<html>
<head>
<meta charset="utf-8">
<title>test IndexedDB - cursor - function</title>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script type="text/javascript">
// ブラウザ対応宣言
window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;
// データベース(IDBDatabase)インスタンス
var db;
// データベース名
var dbName = "TestDB";
// オブジェクトストア名
var objStoreName = "Test1";
/**
* DB接続処理
*/
function openDB() {
// データベースオープン:[名称:TestDB]
var request = indexedDB.open(dbName);
//オープンが正常の場合の関数宣言
request.onsuccess = function(event) {
//データベースインスタンス保存
db = event.target.result;
console.log("DBオープンOK");
};
//エラーの場合の関数宣言
request.onerror = function(event){
console.log("DBオープンエラー");
};
}
/**
* 全データ取得処理
*/
function getAllData(funcCursor = null, funcDataEnd = null) {
//トランザクション
var transaction = db.transaction(objStoreName, 'readonly');
//オブジェクトストアにアクセスします。
var objectStore = transaction.objectStore(objStoreName);
//カーソル開始
var request = objectStore.openCursor();
//カーソルで対応するデータが存在した場合の処理
request.onsuccess = function(event) {
var cursor = event.target.result;
if(cursor) {
if (funcCursor) {
//関数が指定された場合、カーソル処理
funcCursor(cursor.value);
}
//次のカーソルへ
cursor.continue();
} else {
//これ以上のデータは存在しない
if (funcDataEnd) {
//関数が指定された場合、全データ取得後処理
funcDataEnd();
}
}
};
//カーソル取得エラーの場合の関数宣言
request.onerror = function(event) {
console.log('取得失敗。event:', event);
};
}
//レコードデータ退避
var rec = [];
//カーソル処理
function cursorProc(data) {
rec.push(data);
}
//全データ取得後処理
function dataEndProc() {
var str = "<p>";
for (var i = 0; i < rec.length; i++) {
str += "id:" + rec[i]["id"] + "<br />";
}
str += "</p>";
//id="dataarea"の div タグの中身をクリア・設定
$("#dataarea").empty();
$("#dataarea").append(str);
}
//全データ取得処理
function getAllDataProc() {
rec = [];
//各関数を引数にして処理CALL
getAllData(cursorProc, dataEndProc);
}
</script>
</head>
<body>
<h2>test IndexedDB - cursor - 3</h2>
<button id="buttonOpen" onclick="openDB()">DBオープン</button>
<button id="buttonGet" onclick="getAllDataProc()">全データ取得</button>
<br />
<div id="dataarea">
</div>
</body>
</html>
カーソル処理用関数 cursorProc はカーソル処理の中からカーソルデータ内のレコードデータを渡す様に 引き数にレコードデータを持ちます。 cursorProc の処理は特になく、静的変数に配列データとして退避します。
全データ取得後処理関数 dataEndProc は保存された配列のレコードデータを順次 id のみの一覧を作成し div タグ内に設定します。
実際の全データ取得処理ではこれらの関数を引数に渡して getAllData を呼出しています。
カーソル開始のリクエスト openCursor もそうなのですが、IndexedDB の各メソッドを呼び出した後で 処理が成功した時には非同期に onsuccess の定義関数が呼ばれます。
この「非同期」が厄介で、プログラムを組む上で連続的な感じでは記述できません。 リクエストを発行したタイミングと、その後必要とされる処理が別のタイミングで実行されるため、うまく記述しなければなりません。
それで、後処理を別関数として定義し、リクエストを発行する関数に渡してやることになりました。 (これの例として上のプログラムが在るわけですが…)
以上で、全てのデータを読込んだ後で行いたい場合に別関数を与えて行う方法を説明しましたが、 もし、2個のオブジェクトストアが存在し、1個目のオブジェクトストアを全て読込んだ後で、 更に2個目のオブジェクトストアを全て読込んで処理を行いたい場合はどうすればいいのでしょうか。
これに付いての対処の方法は次回の記事で説明したいと思います。
関連する記事
⇒JavaScript IndexedDB の使い方1(データベースオープン)⇒JavaScript IndexedDB の使い方2(データ追加)
⇒JavaScript IndexedDB の使い方3(データ取得)
⇒JavaScript IndexedDB の使い方4(全データ取得)
⇒JavaScript IndexedDB の使い方5(カーソル処理)
⇒JavaScript IndexedDB の使い方6(データ削除)
コメント