优化数据循环

Optimize data looping

本文关键字:循环 数据 优化      更新时间:2023-09-26

我有一个20000-150000行的网格,点击一下我可以选择所有行,然后我使用这个调用来批准它们
这适用于不到1000行的情况,但如果超过1000行,浏览器就会锁定,即使在我单独放置20分钟后也永远不会完成。

我正在寻找能够优化这一过程的解决方案。

$("#approval").on('click',function(){
    var thisgrid = Grid; //my gridwapper
    var spotrows = thisgrid.grid.getSelectedRows();
    var index = 0;
    // console.dir(spotrows);
    if(typeof spotrows.length == 'undefined' || spotrows.length == 0)
    {
        alert('Please select a spot.');
        return;
    }
     for(key in spotrows)
     {
     var spotupdate = {};
     thisgrid.grid.invalidateRow(spotrows[key]);
     spotupdate = thisgrid.dataview.getItem(spotrows[key]);
     spotupdate['Approved'] = (spotupdate['Approved'] == 1) ? 0 : 1;
     thisgrid.dataview.updateItem(spotupdate['id'],spotupdate);

     }
    thisgrid.dataview.refresh();

});

浏览器锁定的原因是Javascript(和UI)在一个线程中运行。这意味着,只要代码正在执行,浏览器就无法处理UI事件(点击、重新绘制等)。

处理大量数据同时保持UI响应的一种方法是将循环分解为多个较小的函数调用,并使用setTimeout对下一个循环段进行排队。类似这样的东西:

$("#approval").on('click',function(){
    var thisgrid = Grid; //my gridwapper
    var spotrows = thisgrid.grid.getSelectedRows();
    function iterate(rows){
        var max = 1000, count = 0;
        for(key in rows){
            // do stuff
            delete rows[key];
            count++;
            if(count == max) {
                setTimeout(function(){
                    iterate(rows);
                }, 0);
                break;
            }
        }
    }
    iterate(spotrows);
});

即使超时设置为0毫秒,这仍然有效,因为setTimeout确保在JS事件循环的下一次传递时调用该函数,从而为处理其他排队事件提供了机会。

关于JS事件循环的更多信息-http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-explained/

我尝试过使用setTimeout,但这并没有提高性能。

这是我使用的解决方案。经过几次测试后,我取出了以下几行,因为它们似乎不需要:

thisgrid.grid.invalidateRow(spotrows[key]);

thisgrid.dataview.refresh();

并添加了非常重要的:

thisgrid.dataview.beginUpdate();

thisgrid.dataview.endUpdate();

以下是完整的代码供参考:这允许在不到2秒的时间内更新100000行。

$("#approval").on('click',function(){
    var thisgrid = Grid; //my gridwapper
    var spotrows = thisgrid.grid.getSelectedRows();
    var index = 0;

    if(typeof spotrows.length == 'undefined' || spotrows.length == 0)
    {
        alert('Please select a spot.');
        return;
    }
    thisgrid.dataview.beginUpdate();
    for(key in spotrows)
    {
       var spotupdate = {};
       thisgrid.grid.invalidateRow(spotrows[key]);
       spotupdate = thisgrid.dataview.getItem(spotrows[key]);
       spotupdate['Approved'] = (spotupdate['Approved'] == 1) ? 0 : 1;
       thisgrid.dataview.updateItem(spotupdate['id'],spotupdate);
       delete spotupdate;
       delete spotrows[key];

     }
    thisgrid.dataview.endUpdate();

});