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,但 IndexedDB 在 WebWorkers 中不可用。我试图找到一种批量插入的方法,但找不到。关于如何在不阻塞 UI 的情况下插入大量对象的任何想法?

4

4 回答 4

40

您走在正确的轨道上,但是您要求浏览器在有机会完成存储一个对象之前存储 35,000 个对象。这是在开始下一个请求之前异步等待一个请求完成的代码(但使用相同的事务):

    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

通过使用回调,你做的一切都是正确的。

Webworker API 尚未被任何主流浏览器实现。有趣的是,它预计是同步的。由于您描述的确切原因,常规 API 是异步的——它不应该阻塞 UI 线程。

使用回调是避免锁定的方法,但是在 35k 个对象时,您会清楚地看到这种范式崩溃了。不幸的是,从我看到的基准测试来看,IDB 的性能还不能与 WebSQL 相提并论。

使用 Chrome 的 LevelDB 有一些新的实验性后端(FF 是 SQLite),但我认为您的经验证明还有一些改进的余地。

于 2012-05-06T21:49:01.100 回答
0

我的猜测很疯狂,但是如果 WebSQL 可以从所谓的“背景页面”获得,并且假设前端和后端之间的消息传递带宽不会以同样的方式锁定 UI,那么背景页面可能会带有可以使用页内消息吗?

于 2012-05-07T08:03:08.020 回答
0

我将数组拆分为 500 个块并使用setTimeout而不是 for 循环。现在 UI 的响应比以前好一点

于 2012-08-08T15:23:09.897 回答