在密集的JavaScript处理过程中,如何(短暂地)将控制权交还给浏览器?

在密集的JavaScript处理过程中,如何(短暂地)将控制权交还给浏览器?,javascript,jquery,Javascript,Jquery,我已经读过关于在密集DOM处理(使用JavaScript)期间使用setTimeout()的文章,但是如何将此函数与下面的代码集成?下面的代码适用于少量选项,但当选项数量过大时,我的“请等待”动画GIF会在本地JavaScript处理时冻结。谢谢 function appendToSelect() { $("#mySelect").children().remove() ; $("#mySelect").html( '<option selected val

我已经读过关于在密集DOM处理(使用JavaScript)期间使用setTimeout()的文章,但是如何将此函数与下面的代码集成?下面的代码适用于少量选项,但当选项数量过大时,我的“请等待”动画GIF会在本地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>'
        ); 
    }
}
函数appendToSelect(){
$(“#mySelect”).children().remove();
$(“#mySelect”).html(
''
+对象数据[0]。名称
+ ''
);
var j=1;
对于(变量i=1;i
您需要重写函数以缓存元素列表,然后使用某种计数器在列表上循环

然后,当计数器在\u wait==0之前到达计数器%max\u num\u时,调用函数本身的超时


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

恰好我刚才发布了关于此的内容。下面是一个定时循环函数:

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();
}
函数processLoop(actionFunc、numTimes、doneFunc){
var i=0;
var f=函数(){
如果(i
对于您的情况,可以这样使用:

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);

}
函数appendToSelect(){
$(“#mySelect”).children().remove();
$(“#mySelect”).html(
''
+对象数据[0]。名称
+ ''
);
var j=1;
processLoop(函数(i){
$(“#mySelect”).append(
''
+对象数据[i].名称
+ ''
); 
},对象数据长度);
}
您需要确保对迭代函数中的obj变量具有闭包或其他访问权限

希望这有帮助。

这里有一个解决方案:

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
}
函数appendToSelect(){
$(“#mySelect”).children().remove();
$(“#mySelect”).html(
''
+对象数据[0]。名称
+ ''
);
splice(0,1);//我们只需要剩余的数据
var appendOptions=function(){
var dataChunk=obj.data.splice(0,10);//配置最后一个数字(“chunk”的大小)以满足您的需要
对于(var i=0;i0){
setTimeout(appendOptions,100);//根据需要更改时间
}
};
appendOptions();//启动它
}
没有解决方案那么优雅,但你明白了。基本上,我在做同样的事情,但都是在你的一个函数中,而不是像他那样把它分解成一个高阶函数。我喜欢他的解决方案,但如果你不喜欢,也许这对你有用


编辑:对于那些没有立即看到它的人来说,此解决方案和的主要区别之一是,此解决方案允许您设置在每个超时之间处理的数据“块”的大小。处理阵列的每个成员后超时。如果我有时间,我会尝试创建一个高阶函数来处理这个问题,这样它会更优雅。但是没有承诺!;)


编辑:下面是我对解决方案的修改,它允许设置“块”大小并更轻松地配置超时值:

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...
}
function incrementallyProcess(workerCallback、数据、chunkSize、超时、completionCallback){
var itemIndex=0;
(功能(){
var remainingDataLength=(data.length-itemIndex);
var currentChunkSize=(remainingDataLength>=chunkSize)?chunkSize:remainingDataLength;
if(itemIndex
希望这能有所帮助——我认为这是两种解决方案的最佳结合注意,第二个匿名函数不再使用索引值,而是简单地传入整个对象(带有值和名称属性);这使得它更简洁,因为当前对象的索引在迭代对象时通常并不那么有用


我相信还有一些事情可以做得更好,但这是留给读者的练习

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

使用该插件,您的代码可以重写为:

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++;
        }
    });
    /////////////////////////////
}
函数appendToSelect(){
$(“#mySelect”).children().remove();
$(“#mySelect”).html(
''
+对象数据[0]。名称
+ ''
);
/////////////////////////////
var i=1;
$.whileAsync({
测试:函数(){i

应该有助于提高反应能力。调整“批量”和“延迟”选项以获得更多控制。

告诉他们使用Chrome,他们将拥有JITted javascript:)