まだ、イマイチ感がある。
注意点
1.PC上のHTMLの場合、データベースのスコープ(有効範囲)はPC単位。
つまりPC上のHTMLで共有してしまう
2.データベースをオープンしたら、必ず自分でクローズすること
クローズし忘れると、次のオープン時にロックしやすい
大抵はF5のオートコミットで済むが、ブラウザを閉じないとダメな場合もある
successイベントは1回のみなので、try catchの後のfinallyでクロースすればいい
const request = window.indexedDB.open("TestDatabase");
request.addEventListener('success', (event) => {
const database = event.target.result;
try {
・・・データ処理・・・
} catch (ex) {
console.log(`${ex}`);
} finally {
database.close();
}
});
しかし、Promiseを使って処理の同期を取りたい場合は・・・
const promise = new Promise( (resolve, reject) => {
const request = window.indexedDB.open("TestDatabase");
request.addEventListener('success', (event) => {
const database = event.target.result;
try {
・・・データ処理・・・
resolve(`xxxx(...): success`);
} catch (ex) {
console.log(`${ex}`);
reject(`xxxx(...): catch(${ex})`);
} finally {
database.close();
}
});
*** エラー処理とか ***
});
return promise;
とすると、resolveの後にfinally句のクローズ処理が通るかどうか?
あまり自信が無い。
と云うのも
function test() {
return true;
alert('OK');
}
のalert(‘OK’);がいつのまにか処理されなくなってたからだ。
upgradeneeded発生時は、後にsuccessイベントが続くので、successイベントに任せればいい
errorイベントも忘れずにクローズ。
request.addEventListener('error', (event) => {
const error = event.target.error;
database.close();
reject(`xxxx(...): error\n${error}`);
});
3.オブジェクトストアの生成・削除はデータベースのバージョンアップ時のみ
4.インデックスの生成・削除もデータベースのバージョンアップ時のみ
5.だが、トランザクションはデータベースのバージョンアップ時は不可
6.トランザクションも自分でcommit、abortすること
commitやabortを忘れるとタイムアウトするまで次の処理がロックする
const trans = database.transaction(オブジェクトストア・リスト);
try {
const objectStore = trans.objectStore(オブジェクトストア);
***データ処理***
trans.commit();
} catch (ex) {
trans.abort();
throw ex;
}
だからと云ってcursorのsuccessイベントは何回も降ってくることが多いので
毎回commitすると、2周目でつまずく
const trans = database.transaction(オブジェクトストア・リスト);
try {
const objectStore = trans.objectStore(オブジェクトストア);
const cursor objectStore.createCursor().onsuccess(event => {
const cursor = event.target.result;
***データ処理***
cursor.continue();
trans.commit(); //毎回コミットは・・・
});
} catch (ex) {
trans.abort();
throw ex;
}
7.インデックスの生成・削除できるタイミングはオブジェクトストアの生成直後だけ
const request = indeedDB.openDatabase(データベース名)
request.addEventListener(`onupgradeneed', (event) => {
const database = event.target.result;
const objectStore = database.createObjectStore(オブジェクトストア名);
objectStore.createIndex(インデックス名);
objectStore.deleteIndex(インデックス名);
});
後でインデックスを調整したい場合は、オブジェクトストアのexports機能を自作して、イジって、importsするしかない。
8.カーソルの生成はデータベースのバージョンアップ時は不可だと思う
9.カーソルのsuccessイベントはカーソルの移動回数分繰り返すので、Promise使った方が良さそう
最終のsuccessイベントは、event.target.result === undefined
なので、うっかりcursor.valueすると痛い。resolveだけ処理すればいい。
const trans = database.transaction(オブジェクトストア名);
const promise = new Promise( (resolve, reject) => {
try {
const objectStore = trans.objectStore(オブジェクトストア名);
const cursor = objectStore.openCursor();
cursor.onsuccess = (event) => {
var cursor = event.target.result;
if (cursor) {
console.log(`${cursor.key} is ${cursor.value}.`);
cursor.continue();
} else {
console.log("end");
resolve(true);
}
};
cursor.onerror = (event) => {
const error = event.target.error;
reject(error);
};
} catch (ex) {
reject(ex);
}
});
return promise;
な感じだった。
データベースの構成をイジる処理をコードしてみると、
何かと面倒くさかったので、
全データベースまたはオブジェクトストア単位でのexports、imports機能を作って、
データを編集するコード(createDatabase、deleteDatabaseとか)を
使いまわしをした方が良さそう。
どうせやることは、
class IndexedDbOp {
constractor(json) {
this.json;
};
const createDatabase = (databaseName) => {
this.json.databases[this.json.databases.length] = {'database':{
'name': databaseName,
'version': 1
}}
return this;
}
const deleteDatabase = (databaseName) => {
this.json.databases = this.json.databases.filter( database => database.name !== databaseName );
return this;
}
・・・以下同文・・・
}
なのにブラウザにはindexedDBのexports、imports機能が付いていない不思議。
※上記のソースコードは雰囲気です。