javascript 在 IndexedDB 的对象存储块中插入大量的 UI

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10471759/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 09:59:44  来源:igfitidea点击:

Inserting large quantities in IndexedDB's objectstore blocks UI

javascriptgoogle-chrome-extensionindexeddb

提问by surya

I want to save some ~35000 objects in my IndexedDB's objectstore. I am using below code to insert.

我想在我的 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  
            };
        });
    });        
};

The above code works fine, but looping and inserting over ~35000 objects makes the UI unresponsive for ~200 seconds. I thought maybe i can use WebWorkers, but IndexedDB is not available inside WebWorkers. I tried to find a way to bulk insert, couldn't find one. Any ideas of how to insert large quantities of objects without blocking the UI?

上面的代码工作正常,但循环和插入超过 35000 个对象会使 UI 无响应约 200 秒。我想也许我可以使用 WebWorkers,但 IndexedDB 在 WebWorkers 中不可用。我试图找到一种批量插入的方法,但找不到。关于如何在不阻塞 UI 的情况下插入大量对象的任何想法?

回答by Doug Reeder

You're on the right track, but you're asking the browser to store 35,000 objects before it's had a chance to finish storing one. Here's code which asynchronously waits for one request to finish before starting the next (but using the same transaction):

您走在正确的轨道上,但是您要求浏览器在有机会完成存储之前存储 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();
            }
        }           
    };      

回答by buley

You're doing everything right by using callbacks.

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

The Webworker API has not yet been implemented by any major browser. Interestingly, it is expected to be synchronous. The regular API is async for the exact reason you describe -- it's not supposed to block the UI thread.

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

Using callbacks is the way to avoid lock ups, but at 35k objects you're clearly seeing this paradigm break down. Unfortunately, IDB performance is not yet on par with WebSQL from the benchmarks I've seen.

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

With Chrome's LevelDB there's been some new experimental backends (FF is SQLite ) but I think your experience proves that there's some room for improvement.

Chrome 的 LevelDB 有一些新的实验性后端(FF 是 SQLite),但我认为你的经验证明还有一些改进的空间。

回答by Marius Kjeldahl

Wild guess from my side, but if WebSQL is available from what is known as a "background page", and assuming the bandwidth of messaging between the front- and backpage does not lock up the UI in the same way, maybe a background page with intra page message could be utilized?

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

回答by surya

I am splitting the array in chunks of 500 and using setTimeoutinstead of for loop. Now the UI responds little better than before

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