IndexedDBにはまってます。(その17)

IndexedDBにはまってます。(その15)に続いてカーソル運用の紹介をします。

移動用メソッド以外に、updateメソッドとdeleteメソッドによるレコードの更新と削除の機能があります。まずは後者で比較的簡単なdeleteメソッドから紹介します。

(その15)の作業を「オブジェクトストアStore_name生成」→レコードの「配列オブジェクトを準備」→「レコード格納」と、「というわけで、レコード格納までは(その14)と同じでした。」まで済ませます。

はい、投稿を前後するのはとっても面倒ですね。

今回のコピペコード全てをテキストファイル「code_IndexedDB_17.txt.zip」にまとめてアップロードしましたので、ダウンロードしてご利用ください。

レコード格納までの結果表示

アプリケーション画面でレコードも確認します。

ブジェクトストアに格納されたレコード
コンソール画面でメソッドを登録

今回(と次回)は、レコードの削除(と更新)による改変処理ですから、トランザクションの生成は’readwrite’モードです。

const tx = db.transaction('Store_name', 'readwrite');

また、レコードの改変処理を行うメソッドはカーソルに入ってきたレコードの処理を行いますが、カーソルの移動はできません。よって前回(その15)のadvanceメソッドと同居になります。

さらに、今回のdeleteメソッドとadvanceメソッドは各々に例外が発生しますので、try文も別々に用意します。

例によって、(個人的に)入れ子にしたくないので、つぎのように前後に並べます。

前回(その15)の「カウント出力」行から「カウントインクリメント」までのカーソル処理ブロックはつぎのように変更します。

console.log(`カーソルの移動は_>${count}回めです。`);
console.log(`カーソルリクエストを参照_>${cursor.request}`);
//操作前のレコードを取得する。
r.push(JSON.parse(JSON.stringify(cursor.value)));
let req = null;
try {
	req = cursor.delete();
	req.addEventListener('success', (e)=>{
		console.log(`レコードの削除に成功しました。`);
	}, false);
	req.addEventListener('error', (e)=>{
		console. error(`レコードの削除に失敗しました。`);
	}, false);
} catch(e) {
	console.error(`カーソルによる操作に失敗しました。`);
	console.dir(e);
}
if(req!==null) {
	try {
		cursor.advance(cursorStep);
	} catch(e) {
		console.error(`カーソルの移動に失敗しました。`);
		console.dir(e);
	}
}
count++;

コードの説明をします。

まず「操作前のレコードを取得する。」です。

(その15)では「cursor.value」だけを取得してましたが、それは削除してしまうのでモニター(観察)するのではなくて取得します。

となると、データベースからの参照を断ち切るため、一度JSON文字列に変換してからJavascriptのオブジェクトにパースします。

将来、バックアップが必要な場合に使える手法になると期待できます。(まだ、そこまで開発はしてませんので予測の範疇です。)

最初のtry文では、deleteメソッドでカーソルの対象レコードを削除します。さらに、成功と失敗イベントが発火しますので受け取り枠を準備します。

そしてdeleteメソッドのリクエストが代入される変数reqがnullでなければ、advanceメソッドによるカーソル移動が行われます。こちらも(その15)と同じっくtry文で包みます。

それでは、つぎのコードをWebブラウザ(Google Chromeを利用)のコンソールにコピー&ペーストし、エンターキーで実行します。

const openRequest = indexedDB.open('DB_name');
openRequest.addEventListener('success', (event)=>{
	const db = event.target.result;
	console.log(`データベースを開始しました。`);
	if(db.objectStoreNames.contains('Store_name')) {
		const tx = db.transaction('Store_name', 'readwrite');
		tx.addEventListener('complete', (event)=>{console.log(`トランザクションが完遂しました。`);}, false);
		tx.addEventListener('error', (event)=>{console.error(`トランザクションでエラーが発生しました。`);}, false);
		tx.addEventListener('abort', (event)=>{console.error(`トランザクションが中断しました。`);}, false);
		const objectStore = tx.objectStore('Store_name');
		//ラングオブジェクト生成
		const range = newRange({start:{v:[2, 'SN0001'], b:false}, end:{v:[5, 'SN0005'], b:false}});
		//カーソル移動方向キーワード
		const direction = 'next';
		//カーソル移動ステップ(整数)
		const cursorStep = 1;
		let cursorRequest;
		try {
			//オブジェクトストアのカーソルを生成する。
			cursorRequest = objectStore.openCursor(range, direction);
		} catch(e) {
			console.error(`カーソルの生成に失敗しました。`);
		}
		if(cursorRequest!==null) {
			//カーソルによるオブジェクトストア操作箇所の始まり
			let r = new Array();
			let count = 0;
			cursorRequest.addEventListener('success', (e)=>{
				const cursor = e.target.result;
				if(cursor===null){
					console.log(`カーソルの移動が終了しました。`);
					if(count===0) console.error(`対象となるレコードがありませんでした。`);
					else {
						console.log(`カーソルの移動が終了しました。_全移動回数_>${count}`);
						console.dir(e.target.source);
						console.dir(r);
					}
				} else {
					console.log(`カーソルの移動は_>${count}回めです。`);
					console.log(`カーソルリクエストを参照_>${cursor.request}`);
					//操作前のレコードを取得する。
					r.push(JSON.parse(JSON.stringify(cursor.value)));
					let req = null;
					try {
						req = cursor.delete();
						req.addEventListener('success', (e)=>{
							console.log(`レコードの削除に成功しました。`);
						}, false);
						req.addEventListener('error', (e)=>{
							console. error(`レコードの削除に失敗しました。`);
						}, false);
					} catch(e) {
						console.error(`カーソルによる操作に失敗しました。`);
						console.dir(e);
					}
					if(req!==null) {
						try {
							cursor.advance(cursorStep);
						} catch(e) {
							console.error(`カーソルの移動に失敗しました。`);
							console.dir(e);
						}
					}
					count++;
				}
			}, false);
			cursorRequest.addEventListener('error', (e)=>{
				console.error(`カーソルの移動の_>${count}回めを失敗しました。`);
			}, false);
			//カーソルによるオブジェクトストア操作箇所の終わり
		}
	} else console.error(`目的のオブジェクトストアはありませんでした。`);
	db.close();
	db.addEventListener('close', ()=>{console.log(`データベースが閉鎖されました。`);}, false);
}, false);
openRequest.addEventListener('error', (event)=>{console.error(`データベースの開始に失敗しました。`);}, false);
コンソール画面の入力と結果表示
オブジェクトストアから削除されたレコード

ちゃんとバックアップ(ぽい)が取れた上で、削除がされている(レコードが消えている。)のを確認できます。

カーソルは付け足しの重なりで処理が進む印象です。つぎのupdateメソッドは、今回の構造の上にさらにてんこ盛りになります。

本当にてんこ盛りにすると、訳わからなくなりますので、なんとか端折れるように工夫します。そかさ。