2008-10-17 11 views
21

我已阅读here关于在密集DOM处理(使用JavaScript)期间使用setTimeout()的帖子,但是如何将此函数与以下代码集成?下面的代码适用于少数选项,但是当选项数量变得太大时,我的“请稍等”动画GIF冻结,而本地JavaScript正在处理。谢谢!在密集的JavaScript处理过程中,我怎样才能将控制权(简单地)返回给浏览器?

function appendToSelect() { 
    $("#mySelect").children().remove() ; 
    $("#mySelect").html(
     '<option selected value="' + obj.data[0].value + '">' 
     + obj.data[0].name 
     + '</option>' 
    ); 
    var j = 1 ; 
    for (var i = 1; i < obj.data.length; i++) { 
     $("#mySelect").append(
      '<option value="' + obj.data[i].value + '">' 
      + obj.data[i].name 
      + '</option>' 
     ); 
    } 
} 
+2

告诉他们使用Chrome浏览器,他们将有JITted JavaScript :) – 2009-02-03 02:04:55

回答

28

这里是一个解决方案:

function appendToSelect() { 
    $("#mySelect").children().remove(); 
    $("#mySelect").html(
    '<option selected value="'+obj.data[0].value+'">' 
    + obj.data[0].name 
    + '</option>' 
); 
    obj.data.splice(0, 1); // we only want remaining data 
    var appendOptions = function() { 
    var dataChunk = obj.data.splice(0, 10); // configure this last number (the size of the 'chunk') to suit your needs 
    for(var i = 0; i < dataChunk.length; i++) { 
     $("#mySelect").append(
     '<option value="' + dataChunk[i].value + '">' 
     + dataChunk[i].name 
     + '</option>' 
    ); 
    } 
    if(obj.data.length > 0) { 
     setTimeout(appendOptions, 100); // change time to suit needs 
    } 
    }; 
    appendOptions(); // kicks it off 
} 

不一样优雅的@Borgar's解决方案,但你的想法。基本上,我正在做同样的事情,但都是在你的一个功能上,而不是像他那样把它分解成一个更高级的功能。我喜欢他的解决方案,但如果你不这样做,也许这会对你有用。


编辑:对于那些不立即看到它,这个解决方案和@Borgar's之间的主要区别之一是,该解决方案允许您设置之间处理数据的“块”的大小每个超时。 @Borgar's超时后处理数组中的每个单个成员。如果我有时间,我会尝试创建一个更高级的函数来处理这个问题,使它更优雅。没有承诺,但! ;)


编辑:所以,这里是我的@Borgar's解决方案,它允许设置一个“块”的尺寸和更容易配置的超时值调整:

function incrementallyProcess(workerCallback, data, chunkSize, timeout, completionCallback) { 
    var itemIndex = 0; 
    (function() { 
    var remainingDataLength = (data.length - itemIndex); 
    var currentChunkSize = (remainingDataLength >= chunkSize) ? chunkSize : remainingDataLength; 
    if(itemIndex < data.length) { 
     while(currentChunkSize--) { 
     workerCallback(data[itemIndex++]); 
     } 
     setTimeout(arguments.callee, timeout); 
    } else if(completionCallback) { 
     completionCallback(); 
    } 
    })(); 
} 

function appendToSelect() { 
    $("#mySelect").children().remove(); 
    $("#mySelect").html(
    '<option selected value="' + obj.data[0].value + '">' 
    + obj.data[0].name 
    + '</option>' 
); 
    obj.data.splice(0,1); // we only want remaining data  
    incrementallyProcess(function(data) { 
    $("#mySelect").append(
    '<option value="' + data.value + '">' 
    + data.name 
    + '</option>' 
    ); 
    }, obj.data, 10, 100, removeAnimatedGifFunction); // last function not required... 
} 

希望帮助 - 我认为这结合了两种解决方案中最好的。 注意,第二个匿名函数不再使用索引值,而只是传入整个对象(使用值和名称属性);这使得它更清洁一些,因为当前对象的索引实际上不是,通常在遍历事物IMO时非常有用。

我相信还有些事情可以做得更好,但这只是对读者的一个练习。 ;)

-1

您需要重写缓存元素列表的函数,然后使用某种计数器遍历列表。

然后当计数器达到计数器%max_num_before_wait == 0时,调用超时返回到函数本身。

确保清除完整列表末尾的缓存和计数器,或者使用具有额外计数参数的辅助功能。

20

恰好我刚刚发布了关于此的帖子here。这里是一个定时循环功能:

function processLoop(actionFunc, numTimes, doneFunc) { 
    var i = 0; 
    var f = function() { 
    if (i < numTimes) { 
     actionFunc(i++); // closure on i 
     setTimeout(f, 10) 
    } 
    else if (doneFunc) { 
     doneFunc(); 
    } 
    }; 
    f(); 
} 

对于您的情况,这将像这样使用:

function appendToSelect() { 

    $("#mySelect").children().remove() ; 
    $("#mySelect").html(
     '<option selected value="' + obj.data[0].value + '">' 
     + obj.data[0].name 
     + '</option>' 
); 
    var j = 1 ; 

    processLoop(function (i){ 
    $("#mySelect").append(
     '<option value="' + obj.data[i].value + '">' 
     + obj.data[i].name 
     + '</option>' 
    ); 
    }, obj.data.length); 

} 

你要确保你有一个封闭或其他一些访问OBJ迭代函数内的变量。

希望这会有所帮助。

4

如果你需要更简单一些,我写了一个jQuery插件来简化异步循环的编写:jQuery Async

使用插件,你的代码可以改写为:

function appendToSelect() { 
    $("#mySelect").children().remove() ; 
    $("#mySelect").html(
     '<option selected value="' + obj.data[0].value + '">' 
     + obj.data[0].name 
     + '</option>' 
    ); 

    ///////////////////////////// 
    var i = 1; 
    $.whileAsync({ 
     test: function(){ i < obj.data.length; } 
     loop: function() 
     { 
      $("#mySelect").append(
       '<option value="' + obj.data[i].value + '">' 
       + obj.data[i].name 
       + '</option>' 
      ); 
      i++; 
     } 
    }); 
    ///////////////////////////// 
} 

应该帮助响应。调整“批量”和“延迟”选项以获得更多控制权。

相关问题