21

IndexedDB のオブジェクトストアに ~35000 個のオブジェクトを保存したいと考えています。以下のコードを使用して挿入しています。

AddListings = function (x2j_list_new, callback) {   
    var transaction = db.transaction(["listings"], IDBTransaction.READ_WRITE);
    var count = 0;
    transaction.oncomplete = function (event) {
        if (callback) {
            console.log('x2jShowListing Added ' + count + '/' + x2j_list_new.length);
                callback([count, x2j_list_new.length]);
            }
    };
    transaction.onerror = function (e) {
       console.log("myError: ", e);  
       if (callback) {
          callback(false);
       }
    };
    var store = transaction.objectStore("listings");

    $.each(x2j_list_new, function (index0, item0) {
        var request = store.put(item0);
        request.onsuccess = function (event) {
            count++;
            // event.target.result  
            };
        });
    });        
};

上記のコードは問題なく動作しますが、35000 個以上のオブジェクトをループして挿入すると、UI が 200 秒間応答しなくなります。WebWorkers を使用できるのではないかと思ったのですが、WebWorkers 内で IndexedDB を使用することはできません。一括挿入する方法を見つけようとしましたが、見つかりませんでした。UI をブロックせずに大量のオブジェクトを挿入する方法のアイデアはありますか?

4

4 に答える 4

40

あなたは正しい道を進んでいますが、ブラウザが 1 つの保存を完了する機会を得る前に、35,000 個のオブジェクトを保存するようにブラウザに要求しています。次のリクエストを開始する前に、1 つのリクエストが完了するのを非同期的に待機するコードを次に示します (ただし、同じトランザクションを使用します)。

    openRequest = window.indexedDB.open("MyDatabase", 1);
    openRequest.onerror = function(event) {
        console.error(event);
    };
    openRequest.onsuccess = function (event) {
        var db = openRequest.result;
        db.onerror = function(event) {
            // Generic error handler for all errors targeted at this database's requests
            console.error(event.target);
            window.alert("Database error: " + event.target.wePutrrorMessage || event.target.error.name || event.target.error || event.target.errorCode);
        };
        var transaction = db.transaction('item', "readwrite");
        var itemStore = transaction.objectStore("item");
        putNext();

        function putNext() {
            if (i<items.length) {
                itemStore.put(items[i]).onsuccess = putNext;
                ++i;
            } else {   // complete
                console.log('populate complete');
                callback();
            }
        }           
    };      
于 2012-12-02T05:37:34.787 に答える
0

私の側からのワイルドな推測ですが、WebSQL が「バックグラウンド ページ」として知られているものから利用可能であり、フロント ページとバックページの間のメッセージングの帯域幅が同じように UI をロックしないと仮定すると、おそらくバックグラウンド ページページ内メッセージを利用できますか?

于 2012-05-07T08:03:08.020 に答える
0

配列を 500 個のチャンクに分割し、for ループの代わりにsetTimeoutを使用しています。UI の応答が以前より少し改善されました

于 2012-08-08T15:23:09.897 に答える
0

コールバックを使用して、すべてを正しく行っています。

Webworker API は、主要なブラウザーにはまだ実装されていません。興味深いことに、同期であると予想されます。通常の API は、説明した正確な理由で非同期です。UI スレッドをブロックすることは想定されていません。

コールバックを使用することはロックアップを回避する方法ですが、35k オブジェクトでは、このパラダイムが崩れていることがはっきりとわかります。残念ながら、IDB のパフォーマンスは、私が確認したベンチマークではまだ WebSQL と同等ではありません。

Chrome の LevelDB では、いくつかの新しい実験的なバックエンド (FF は SQLite です) がありましたが、あなたの経験は改善の余地があることを証明していると思います。

于 2012-05-06T21:49:01.100 に答える