IndexedDB使用とピットガイド


概要


この文書では、IndexedDBの使用方法と使用シーンについて説明し、よくある質問に答えます.
また,MDNにおける関連文書は関連論理性に乏しいため,容易に理解できない.この文書では、プロジェクトで一般的なデータストレージと操作要件によってコンテンツの組織を行います.
読者は、本明細書でIndexedDBをプロジェクトで正しく使用することを学び、アプリケーションにローカルストレージ能力をもたらし、一般的な問題を回避することができる.

理由:開発者はローカルで永続的なストレージを必要とする


いくつかの大きなSPAページの開発を行うには、いくつかのデータのローカルストレージが必要です.
データ量が少ない場合は、SessionStorageまたはLocalStorageで保存できますが、データ量が大きい場合や、一定の仕様に合致する場合は、データベースを使用してデータの保存を行うことができます.
ブラウザが提供するデータベースには、web sqlIndexedDBの2種類があります.HTML 5が廃棄されたweb sqlよりもIndexedDBの方がおすすめです.

こうぞう


次に,IndexedDB全体の構造を1枚の図で理解する.
クラス比sql型データベース、IndexedDB中のDB(データベース)はsql中のDBであり、Object Store( ) Itemは表中の1本の に等しい.

IndexedDBの使用


ここでは、IndexedDBの構造に基づいて動作を紹介し、このストレージスペースについて初歩的な理解を得ることができます.主に次のように説明します.
  • データベース操作
  • データテーブル操作
  • データ操作
  • データベース操作


    データベースの作成または開く

    IndexedDBの最初のステップは、データベースを作成または開くことです.window.indexedDB.open(DBName)というAPIを使用して操作を行います.具体例は次のとおりです.
    const request = window.indexedDB.open('test');
    
    request.onupgradeneeded = function (event) {
        
    }
    
    request.onsuccess = function(event) {
        //request === event.target;
    }
    request.onerror = function(event) {}

    このインタフェースを呼び出すと、現在のデータベースが存在しない場合、新しいデータベースが作成されます.
    データベースが接続を確立すると、IDBOpenDBRequestオブジェクトが返されます.
    接続が正常に確立されると、onsuccessイベントがトリガーされ、関数パラメータeventtarget属性がrequestオブジェクトになります.
    データベースの作成またはバージョンの更新時にonupgradeneededイベントがトリガーされます.

    データベースのバージョン番号の更新

    window.indexedDB.openの2番目のパラメータはバージョン番号です.指定しない場合、デフォルトのバージョン番号は1です.具体例は次のとおりです.
    const request = window.indexedDB.open('test', 2);

    データベースのschema( )を更新する必要がある場合は、バージョン番号を更新する必要があります.このとき、以前のバージョンよりも高いバージョン番号を指定すると、onupgradeneededイベントがトリガーされます.同様に、このデータベースが存在しない場合もイベントがトリガーされ、バージョンがセットトップバージョンに更新されます.
    バージョン番号はUnsigned long longの数字であり、これは非常に大きな整数であることを意味します.ただし、小数ではありません.そうしないと、最も近い整数に変換され、onUpgradeneededイベントがトリガーされない可能性があります.

    きおくくうかんさぎょう


    ストレージスペースの作成

    createObjectStoreを使用してストレージスペースを作成します.同時に、createIndexを使用してインデックスを作成します.具体例は次のとおりです.
    var request = window.indexedDB.open('test', 1);
    
    request.onupgradeneeded = function (event) {
        var db = event.target.result;
        var objectStore = db.createObjectStore('table1', {keyPath: 'id', autoIncrement: true});
    
        objectStore.createIndex('name', 'name', {unique: false});
    }
    
    request.onerror = function (event) {
        alert("Why didn't you allow my web app to use IndexedDB?!");
    };

    注意:onupgradeneededコールバック関数でのみストレージスペースを作成できますが、データベースが開いたsuccessコールバック関数では作成できません.createObjectStoreによってストレージスペースを作成できます.2つのパラメータを受け入れます.
  • の最初のパラメータ、記憶空間の名前、すなわち私たちの上のcustomersです.
  • の2番目のパラメータは、記憶されたkeyPathの値を記憶対象の属性として指定し、この属性は記憶空間データを取得する際にkey値として使用することができる.autoIncrementは、keyの値が増加したかどうかを指定します(key値がデフォルトの1から2^53までの整数の場合).
  • createIndexは、現在の記憶領域にインデックスを設定することができる.3つのパラメータを使用できます.
  • 最初のパラメータ、インデックスの名前.
  • の2番目のパラメータは、格納されたデータのどの属性に基づいてインデックスを構築するかを指定します.
  • 第3の属性、optionsオブジェクト、属性uniqueの値がtrueであることは、インデックス値が等しくないことを示す.

  • データ操作


    取引

    IndexedDBでは、トランザクションを使用してデータベースの操作を行うこともできます.トランザクションには3つのパターンがあります(定数は破棄されました):
  • readOnly、読み取り専用です.
  • readwrite、読み書き.
  • versionchange、データベースバージョンが変更されました.

  • トランザクションを作成する場合は、上からモードを選択する必要があります.指定しない場合は、デフォルトは読み取り専用モードです.具体例は次のとおりです.
    const transaction = db.transaction(['customers'], 'readwrite');

    トランザクション関数transactionの最初のパラメータは、関連付けが必要な記憶領域であり、2番目のオプションパラメータはトランザクションモードである.上記と同様に、トランザクションが成功するとonsuccess関数がトリガーされ、失敗するとonerror関数がトリガーされます.
    トランザクションの操作はすべて原子的です.

    データの追加


    ストレージスペースの初期化が完了すると、ストレージスペースにデータを入れることができます.addメソッドを直接呼び出すと、データを記憶領域に格納できます.具体的な例は以下のとおりです.
    var request = window.indexedDB.open('test', 1);
    
    request.onsuccess = function (event) {
        var db = event.target.result;
    
        var transaction = db.transaction(['table1'], 'readwrite');
    
        var objectStore = transaction.objectStore('table1');
    
        var index = objectStore.index('name');
    
        objectStore.add({name: 'a', age: 10});
        objectStore.add({name: 'b', age: 20});
    }

    注意:addメソッドの2番目のパラメータkey値は、指定された記憶領域のkeyPath値です.datakeyPath値が含まれている場合、またはこの値が自己付加価値である場合、このパラメータは省略できます.

    データの検索


    特定の値によるデータの取得


    ストレージスペースからデータを取得する必要がある場合は、次の方法でデータを取得できます.
    var request = window.indexedDB.open('test', 1);
    
    request.onsuccess = function (event) {
        var db = event.target.result;
    
        var transaction = db.transaction(['table1'], 'readwrite');
    
        var objectStore = transaction.objectStore('table1');
    
        var request = objectStore.get(1);
    
        request.onsuccess = function (event) {
            //   request.result     !
            console.log(request.result);
        };
    
        request.onerror = function (event) {
            //     !
        };
    }

    カーソルによるデータの取得


    ストレージスペース全体のデータを便利にする必要がある場合は、カーソルを使用する必要があります.カーソルの使用方法は次のとおりです.
    var request = window.indexedDB.open('test', 1);
    
    request.onsuccess = function (event) {
        var db = event.target.result;
    
        var transaction = db.transaction(['table1'], 'readwrite');
    
        var objectStore = transaction.objectStore('table1');
    
        var request = objectStore.openCursor();
    
        request.onsuccess = function (event) {
            var cursor = event.target.result;
            if (cursor) {
                //   Object.assign               
                console.log(Object.assign(cursor.value));
                cursor.continue();
            }
        };
    
        request.onerror = function (event) {
            //     !
        };
    }

    カーソルを使用するときに注意すべき点は、カーソルがストレージ領域全体を便利にしているが、所定の条件の値が見つからない場合でも、onsuccess関数がトリガーされます.openCursoropenKeyCursorには2つのパラメータがあります.
  • 最初のパラメータで、範囲を巡回し、カーソルのアクセス範囲を指定します.この範囲は、IDBKeyRangeパラメータの方法によって取得される.範囲パラメータの具体例は、
    //     key === 1
    const singleKeyRange = IDBKeyRange.only(1);
    
    //     key >= 1
    const lowerBoundKeyRange = IDBKeyRange.lowerBound(1);
    
    //     key > 1
    const lowerBoundOpenKeyRange = IDBKeyRange.lowerBound(1, true);
    
    //     key < 2
    const upperBoundOpenKeyRange = IDBKeyRange.upperBound(2, true);
    
    //     key >= 1 && key < 2
    const boundKeyRange = IDBKeyRange.bound(1, 2, false, true);
    
    index.openCursor(boundKeyRange).onsuccess = function(event) {
      const cursor = event.target.result;
      if (cursor) {
        // Do something with the matches.
        cursor.continue();
      }
    };
  • である.
  • の2番目のパラメータ、便利順序、カーソル便利時の順序と、同じid(keyPath属性指定フィールド)が繰り返される場合の処理方法を指定します.範囲変更は、特定の文字列(IDBCursorの定数が破棄された)によって取得される.次のようになります.
  • nextは、移動後から全てのデータ(重複データを含む)
  • を取得する.
  • prevは、後から全てのデータ(重複データを含む)
  • を取得する.
  • nextuniqueは、行き先からデータを取得する(重複データは第1条のみ、インデックス重複は重複とみなす、以下同)
  • .
  • prevunique、後進からデータを取得する(重複データは第1条のみ取る)
  • .

    ループ順序パラメータの具体例は次のとおりです.
    var request = window.indexedDB.open('test', 1);
    
    request.onsuccess = function (event) {
        var db = event.target.result;
    
        var transaction = db.transaction(['table1'], 'readwrite');
    
        var objectStore = transaction.objectStore('table1');
    
        var lowerBoundOpenKeyRange = IDBKeyRange.lowerBound(1, false);
        var request = objectStore.openCursor(lowerBoundOpenKeyRange, IDBCursor.PREV);
    
        request.onsuccess = function (event) {
            var cursor = event.target.result;
            if (cursor) {
                //   Object.assign               
                console.log(Object.assign(cursor.value));
                cursor.continue();
            }
        };
    
        request.onerror = function (event) {
            //     !
        };
    }

    索引の使用


    前にデータベースを構築したとき、2つのインデックスを作成しました.インデックスによるデータ取得も可能になりました.彼の本質は,以前にデータを取得したAPIによって行われたが,従来用いられていたkeyPath属性をインデックス指定属性に変換しただけである.具体例は次のとおりです.
    var request = window.indexedDB.open('test', 1);
    
    request.onsuccess = function (event) {
        var db = event.target.result;
    
        var transaction = db.transaction(['table1'], 'readwrite');
    
        var objectStore = transaction.objectStore('table1');
    
        var index = objectStore.index('name');
    
        //    ,get  
        index.get('a').onsuccess = function (event) {
            console.log(event.target.result);
        }
    
        //    ,      
        index.openCursor().onsuccess = function (event) {
            console.log('openCursor:', event.target.result.value);
        }
    
        //    ,     ,           :      value        ,      
        index.openKeyCursor().onsuccess = function (event) {
            console.log('openKeyCursor:', event.target.result);
        }
    }

    データの変更


    ストレージ領域のデータを変更する必要がある場合は、次のAPIを使用します.
    var objectStore = transaction.objectStore("customers");
    
    var request = objectStore.put(data);
    
    request.onsuccess = function (event) {
        
    }

    注:putメソッドは、既存のデータを修正するだけでなく、ストレージスペースに新しいデータを追加することもできます.

    データの削除


    不要なデータを削除する必要がある場合は、次の方法で実行できます.
    var objectStore = transaction.objectStore("customers");
    
    var request = objectStore.delete(name);
    
    request.onsuccess = function (event) {
        
    }

    例外処理


    ブラウザで次の操作が行われている場合、indexedDBに異常が発生する可能性があります.
  • ユーザ消去ブラウザキャッシュ
  • メモリ容量がサイズ制限
  • を超える.
    この場合,エラーをキャプチャし,ユーザにヒントを与える必要がある.この章は本文の重点ではなく,これ以上省略する.

    拡張の注意事項


    値の関連付け


    key値が許容できるデータ型

    IndexedDBでは、キー値ペアのkeyの値は、以下のいくつかのタイプの値を受け入れることができる.
  • number
  • data
  • string
  • binary
  • array

  • 詳細については、文書ここを参照してください.

    key pathが許容できるデータ型

    keyの値がプライマリ・キー、すなわちkeyPathになると、その値は以下の数種類しかありません.
  • Blob
  • File
  • Array
  • String

  • 注意:key pathにスペースは表示されません.
    詳細については、文書ここを参照してください.

    valueが許容できるデータ型

    IndexedDBにおいて、valueは、例えばString、Date、ImageDateなどのECMA−262のすべてのタイプの値を受け入れることができる.

    取引関連


    トランザクションが中断されるとkey値の自己増加に影響しますか?

    IndexedDBは、key値が指定されていない場合に自己増加したkey値を採用する.トランザクションが途中で中断された場合、key値の自己増加は、中断されたトランザクションが開始される前のkeyから開始されます.

    セキュリティ関連

    IndexedDBもブラウザどうげんせんりゃくによって制限されている.

    ユーザー関連


    キャッシュをクリア


    ユーザーがブラウザキャッシュをクリアすると、IndexedDBに関連するデータがクリアされる可能性があります.

    アクセス権


    一部のブラウザでは、Safariの携帯電話版プライバシーモードのようにIndexedDBにアクセスすると、権限がないことによる異常(LocalStorage)が発生し、異常処理が必要になる場合があります.

    まとめ

    IndexedDBはローカルストレージにおいてかけがえのない役割を果たし、リレーショナルデータベースweb sqlに代わる製品であり、大量のデータを格納することができる.オフラインストレージを使用する必要がある多くのシーンでは、効果的なサポートを提供します.
    しかしながら、IndexedDBは、使用中に発生する可能性のあるいくつかの問題を回避したり、不利な影響をもたらす可能性のある許容誤差処理を回避する必要がある.これにより、アプリケーションに大きな影響を及ぼすことはありません.

    参考文献

  • ブラウザの同源ポリシー
  • indexedDB MDNを使用して入門
  • IndexedDB APIリファレンス
  • W 3 C IndexedDB 2.0仕様