Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/478.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在中断长时间运行的JavaScript任务时,避免强制延迟setTimeout_Javascript_Performance_Internet Explorer_Settimeout - Fatal编程技术网

在中断长时间运行的JavaScript任务时,避免强制延迟setTimeout

在中断长时间运行的JavaScript任务时,避免强制延迟setTimeout,javascript,performance,internet-explorer,settimeout,Javascript,Performance,Internet Explorer,Settimeout,我在JavaScript中有一个长时间运行的任务,我用一系列嵌套的setTimeout(processChunk,0)将其分解成块,类似于前面所描述的。但是,对于每次调用,setTimeout会增加4 ms或更多的额外延迟。这种行为在不同的浏览器中是不同的 当我试图将每个数据块的处理时间保持在50毫秒或更短时,这些额外的延迟将使总处理时间至少增加10% 我的问题是:我能否避免额外的延迟(从而提高处理速度),同时保持与ES3浏览器和旧IE浏览器的向后兼容性?这个问题有一个简单的解决方法。由于set

我在JavaScript中有一个长时间运行的任务,我用一系列嵌套的
setTimeout(processChunk,0)
将其分解成块,类似于前面所描述的。但是,对于每次调用,
setTimeout
会增加4 ms或更多的额外延迟。这种行为在不同的浏览器中是不同的

当我试图将每个数据块的处理时间保持在50毫秒或更短时,这些额外的延迟将使总处理时间至少增加10%


我的问题是:我能否避免额外的延迟(从而提高处理速度),同时保持与ES3浏览器和旧IE浏览器的向后兼容性?

这个问题有一个简单的解决方法。由于
setTimeout
的最小延迟是从设置计时器时开始测量的,因此请确保在处理每个数据块之前至少设置10–15毫秒的计时器。当设置了多个
setTimeout
时,它们会排队,并在前一个之后立即调用下一个,而不会产生额外的延迟。这只能通过2个活动计时器完成:

function runLongTask() {
  var complete = false;
  function processChunk() {
    if(!complete) {
      /* ... process chunk, set complete flag after last chunk ... */
      //set new timer
      setTimeout(processChunk);
    } else {
      /* ... code to run on completion ... */
    }
  }
  //set a timer to start processing
  setTimeout(processChunk);
  //set an extra timer to make sure 
  //there are always 2 active timers,
  //this removes the extra delay provided
  //that processing each chunk takes longer
  //than the forced delay
  setTimeout(processChunk);
}
下面是一个工作演示,比较了变通方法和在处理每个块后设置新的
setTimeout
的传统方法。在解决方案中,总是会预先设置一个额外的
setTimeout
,将每个区块的处理时间减少约4 ms或更多(10个区块约40 ms或更多,如下所示),前提是每个区块至少需要4 ms的处理时间。请注意,该解决方案演示了仅使用2个活动计时器

函数runforatelast15ms(){
var d=(+新日期)+15;
而(+新日期0){
//进程块
runForAtLeast15ms();
//设置新计时器
设置超时(运行程序);
}else if(重复===0){
//向控制台报告结果
console.log((解决方法?'workaround':'Traditional')+
“方法:”+
((+新日期)-startTime)+“ms”);
//如果提供,则调用next()函数
next&&next();
}
重复--;
}
设置超时(运行程序);
如果(解决方法){
//确保始终有2个
//通过设置额外的计时器来运行计时器
//一开始
设置超时(运行程序);
}
}
//第一:重复15毫秒的跑步10次
//重复设置超时
testTimeout(10,函数(){
//然后:重复15毫秒的跑步10次
//使用重复设置的2 setTimeout
testTimeout(10,false,true);

});你在问问题的同时回答了自己的问题。@Everald,没错。最近,我独自一人解决了这个问题,并找到了一个解决方案,我想记录并分享。通过分享,有人甚至可以提供更好的解决方案。