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

私には数年前からの開発課題があります。自己研鑽とデジタル環境の進歩のおかげ様で、ようやく挑めるような気がしています。

開発プラットホームはWebブラウザ上と決めていて、いわゆるウェブアプリケーションの範疇になります。

まあ、完成してもしなくてもいいのですが「前向きに、」と考えています。そのくせ、PHPを学習してWordPressのテーマを作るような道草もたくさんしてます。

その開発課題には、ブラウザに装備されたIndexedDB(Indexed Database)というデータベースを利用しなくてはなりません。この存在がプラットホームを決定する要因であったとも言えます。

開発の設計を行うためには、どうしてもデータベースについての十分な理解が必要です。根底からとは望みませんが、木の幹ぐらいからの理解が必要だろうと考えて「IndexedDB API」の学習を始めました。

もちろん興味本位でもあったのですが、理解が進むにつれ、思考階層の交錯する煩雑さに閉口する毎日です。ともあれ、自らの備忘のために学習経緯などを投稿してまいります。

さきに、世の中にはIndexedDBを利用するためのライブラリもあります。

Dexie.jsで始めるIndexedDB(感謝。)とかを読むとIndexedDBのこともざっくり判ってよいです。

これを使えばいいんでないと思われる(私も思った)かもしれません。でも「その中はどうなっているの?」って考えちゃいますし、その利用によって排除されてしまう可能性(設計などの)があるかと思うと…、ダンジョンの中をダウンジングをしまくるような気性の私は、初歩からのIndexedDB学習に赴かざるを得ませんでした。

というわけで、ダウンジング棒を握りしめてIndexedDB APIに踏み込むあたりから話をはじめます。

試験用ソースコードにあるCreate項目の日付は昨年2023年12月26日となっています。以前から準備はしていましたが本格的に挑んだのはその頃になります。現時点でふた月ぐらい経っています。

当時はIndexedDBが難敵であることも知らずに、自分用のライブラリを作るピクニック気分(知らぬ仏様でした。)で準備を始めたようです。

IndexedDBについては書籍がなく、あまり情報もなかったので、以前の準備で見つけたuhyohyo.net「JavaScript初級者から中級者になろう」(感謝。)を基本的な理解のため、参考にいたしました。

(ご注意!現在はIndexedDBは3系らしいのですが、ここではIndexedDBの1系でお話が進んでいるようです。刷新もされていない様子です。でも基本は同じです。よね?)

このサイト内のここら辺をタラララーと読むと「あ、やば。大変かも、」と学ぶことの多いことを知ることができます。

それでMDN Web DocsIndexedDB API(感謝。)では、いろんな情報の最終確認をさせてもらってます。
自分のスキルではMDNだけでアルゴリズムを構築していくのは少々難しいので、いろんな人のお話(サイト)をうかがってます。ChatGPTさんにもお世話になってます。

「MDN Web Docs」の「IndexedDB API」ページ

参考元を紹介していたら前置きが長くなってしまいました。本題にかかります。

紹介する内容は、今現在の私の理解の範疇にあり、間違いや不足もあることにご留意ください。

最初の一歩です。

データベースを利用するためにはメソッドopen()で開きます。データベースがあろうがなかろうが関係なく、ともかく名前(仮にDB_nameとします。)を指定して次のように開きます。

const openRequest = indexedDB.open('DB_name', DB_version);

するとindexedDBは、DB_nameという名前のデータベースが存在すればそれを、存在しなければ生成して開いてくれます。

このDB_nameの後ろにパラメータDB_version(ここでの名前)がありますが、省略しても動作します。

データベースには正の整数でバージョンが振られています。よって、DB_versionには正の整数が代入されます。

データベースのレコードデータを利用する操作ではバージョンを指定しなくても大丈夫なのですが、データベースの構造に変更を加えようという操作ではバージョンをコントロールする必要があります。

データベーが存在しない状態であればバージョンのコントロールの必要はないので、省略(空)します。

ここからが重要です。

開くコマンドが発生した時に、DB_versionの値が、データベースが呼び出される前のバージョンより大きな整数であれば、アップグレード(onupgradeneeded)イベントが必ず発火します。存在しないデータベースを開くとなれば、バージョンが0から1へアップグレードすることになり、やはり発火します。それ以外では発火しません。

このアップグレードイベントは何より先に発火して処理されます。この処理の時だけデータベースの構造にいろいろと変更が施せます。変更の必要がなければアップグレードイベントが発火しないようにバージョンを現行と揃えるか、省略します。

どこかに「IndexedDBに組み込みのスキーマバージョニングで、サーバサイドのデータベースにない仕組み。」なんて書いてありました。特殊なものだそうです。でも、データベースのことをよく知らんかった私にはどうでもよいので、そういう仕組みと理解しました。

つぎは、上の定数openRequestに返ってくるアップグレードイベントを受けて「データベースの準備処理」を書き込む枠になるコードです。

openRequest.addEventListener('upgradeneeded', (event) => {
	(データベースの準備処理)
}, false);
openRequest.onupgradeneeded = (event) => {
	(データベースの準備処理)
}, false);

二種類の表記を紹介しましたが同じことです。私はaddEventListenerによる記述が好みなので、この後はそっちばかりで記述します。ご了承ください。

バージョンが変わるとアップグレード(onupgradeneeded)イベントはかならず発火します。それが発火した後に、もしくは発火しなければ最初に、データベースが無事に開いた成功(onsuccess)イベントが発火します。

つぎは、定数openRequestに返ってくる成功イベントを受けて「データベースの利用処理」を書き込む枠になるコードです。

openRequest.addEventListener('success', (event)=>{
	(データベースの利用処理)
}, false);

アップグレード(onupgradeneeded)と成功(onsuccess)で「準備」と「利用」に概念を分けています。概ね合致していると思います。

そしてデータベースが開けないと失敗(onerror)イベントが発火します。

つぎは、定数openRequestに返ってくる失敗イベントを受けて「データベースのエラー処理」を書き込む枠になるコードです。

openRequest.addEventListener('error', (event)=>{
	(データベースのエラー処理)
}, false);

存在しないデータベースの名前を指定すると新しく生成してしまう仕組みなので、作為的にバージョンを偽ったりしないと発火しないようです。

最後にデータベースを閉じると発火する閉鎖(onclose)イベントです。これはIndexedDBの2系以降に発火するようになったと言われています。

何度か試行錯誤をしたのですが、いまのところイベントの受け取りが確認できておりません。他の方々も同様な様子です。

たしかに、イベントを受け取れたからといって確認以上の実用性は感じられません。実装が後回しになっているのでしょうか。

はまったシリーズ(その1)でした。今後は「準備」と「利用」について少しづつ階層を潜っていきます。

どうか続けられますように。そかさ。