【问题标题】:Setting JavaScript Timeout limit in Google Chrome在 Google Chrome 中设置 JavaScript 超时限制
【发布时间】:2011-06-13 21:54:21
【问题描述】:

是否可以增加 JavaScript 的超时限制?

如果我的脚本执行时间超过 20/30 秒,chrome 将弹出不负责任的页面对话框。

制作更高效的脚本对我没有帮助,因为脚本有时需要对函数进行一百万或十亿次迭代

【问题讨论】:

  • 请问为什么您需要循环一个函数十亿次?我有一种感觉,这个问题的解决方案在于优化你的算法,而不是增加时间限制。
  • 我正在计算获得不同扑克手牌的机会,这有 5 张牌是我需要循环的 2598960 种可能性。
  • 那么与其循环遍历所有这些可能性,为什么不应用一些简单的统计属性/公式呢?您的计算似乎可以很好地利用 AdditionMultiplicationConditional 概率公式。
  • 我数学不是很好,我让用户选择已知的卡片,以及总共有多少张卡片
  • 啊,我明白了。好吧,如果您希望很多人使用它,那么您绝对应该对数学方法进行一些研究,因为它们会更有效率,使用 lass hack-arounds,并提供整体更好的体验。也许这个页面对你有用:stats.gla.ac.uk/steps/glossary/probability.html#condprob

标签: javascript google-chrome


【解决方案1】:

在步骤/块上拆分功能并在setInterval(function(){}) 中运行这些功能。 这种方式页面将是响应式的,您将能够通知用户执行进度,您将完成您的工作。

UPDATE:这是一个简单的函数 worker 执行每次迭代的函数, chunksz - 在单个块中运行的迭代次数 maxit - 迭代总数。

function task(worker, chunksz, maxit)
{
  var idx = 0;
  var xint = null;
  function exec_chunk() 
  {
     for(var n = 0; n < chunksz; ++n)
     {
       if(idx >= maxit) { return; }
       worker(idx++);
     }
     setTimeout(exec_chunk,1);
  }
  exec_chunk();
}

这是一个例子:http://jsfiddle.net/Ed9wL/ 如您所见,您按顺序获得了所有迭代。

UPDATE2

假设你有一个循环:

 for(var i=0; i<100000; ++i) { ... do something ... }

然后你需要将循环体包装成一个函数,并像这样调用上面的task

task(function(i){ ... do something ... },100, 100000);

或者像这样:

function loopBody(i){ ... do something ... }
task(loopBody,100, 100000);

【讨论】:

  • 查看我自己答案的评论,我需要以正确的顺序循环遍历它,所以我不能使用'setInterval(function(){})',但我正在使用它在计算的开始。
  • @Tyilo:您必须发布一些有效的东西......您发布的内容没有任何作用,您知道,缺少全局变量。如果你的函数太复杂,你应该创建一个缩减并发布它。请记录您的代码,如果需要太多时间来理解,我无法为您提供帮助。
  • @Tyilo,我尝试了一些方法,仍然不清楚您的函数应该做什么,但基本上,您需要在超时的情况下调用递归函数。由于我不知道您的功能应该做什么,我不知道行为是否受到影响。测试一下,如果有任何问题,请告诉我jsfiddle.net/mendesjuan/9HKpb/1
  • @Tyilo:有趣的家伙,你的函数对我来说没有意义,我知道它没有产生相同的结果,但我不会花时间调试它为什么没有。如果你正确地记录了你的函数应该做什么,也许我可以改变更多的逻辑来获得正确的结果。无论如何,该示例让您充分了解如何使用超时分解计算
  • @Tyilo:顺便说一句,使用全局变量的递归听起来确实是错误的
【解决方案2】:

当您需要在客户端进行大量处理时,您需要将工作拆分为单独的线程。浏览器只有一个线程来处理用户输入(事件)和处理 JS。如果你处理了太多的 JS 而没有让步,那么 UI 就会变得无响应并且浏览器会不高兴。

如何让你的脚本屈服?新方法是使用网络工作者 http://www.whatwg.org/specs/web-workers/current-work/ 。这通过创建一个单独的线程来运行你的 JS 来工作,线程线程不访问 DOM 并且可以并发运行。

但是,并非所有浏览器都存在这种新技术。对于较旧的浏览器,您可以通过让脚本通过超时调用自身来拆分您的工作。每当发生超时时,脚本都会让浏览器运行其事件,一旦浏览器完成,您的下一个超时将被触发。

示例 http://jsfiddle.net/mendesjuan/PucXf/

var list = [];
for (var i = 0; i < 500000; i++) {
   list.push(Math.random());
}


function sumOfSquares(list) {  
  var total = 0;
  for (var i = 0; i < list.length; i++) {
      total += list[i] * list[i];
      // DOM manipulation to make it take longer
      var node = document.createElement("div");
      node.innerHTML = "Sync temp value = " + total;
      document.body.appendChild(node);
  }
    return total;
}


function sumOfSquaresAsync(arr, callback) {
  var chunkSize = 1000; // Do 1000 at a time
  var arrLen = arr.length;
  var index = 0;
  var total = 0;  

  nextStep();

  function nextStep() {
     var step = 0;
     while (step < chunkSize && index < arrLen) {
       total += arr[index] * arr[index];
       // DOM manipulation to make it take longer
       var node = document.createElement("div");
       node.innerHTML = "Async temp value = " + total;
       document.body.appendChild(node);         
       index++;
       step++;
     }

     if (index < arrLen) {
        setTimeout(nextStep, 10);
     } else {
       callback(total);
     }
  }
}



sumOfSquaresAsync(list, function(total) {console.log("Async Result: " + total)});

//console.log("Sync result" + sumOfSquares(list));

jsfiddle上的例子把同步调用注释掉了,你可以把它放回去看看浏览器爬起来了。请注意,异步调用确实需要很长时间才能完成,但它不会导致长时间运行的脚本消息,它允许您在计算时与页面交互(选择文本、按钮悬停效果)。您可以看到它在右下角的窗格中打印部分结果。

更新 http://jsfiddle.net/mendesjuan/PucXf/8/

让我们尝试使用 c-smile 的任务函数来实现平方和。我认为他缺少一个参数,一个在任务完成时回调的函数。使用task 允许我们创建多个分块函数,而无需重复调用 setTimeout 和迭代的工作。

/**
 * @param {function} worker. It is passed two values, the current array index, 
 *        and the item at that index
 * @param {array} list Items to be traversed
 * @param {callback} The function to call when iteration is finished;
 * @param {number} maxit The number of iterations of the loop to run 
 *        before yielding, defaults to 1000
 */
function task(worker, list, callback, maxit)
{
  maxit = maxit || 1000; 
  var idx = 0;
  exec_chunk();
  function exec_chunk() 
  {
     for(var n = 0; n < maxit; ++n)
     {
       if(idx >= list.length) {
         callback(); 
         return;
       }
       worker(idx, list[idx]);
       idx++;
     }
     setTimeout(exec_chunk,1);
  }
}


function sumOfSquaresAsync(list, callback) 
{
   var total = 0;

   // The function that does the adding and squaring
   function squareAndAdd(index, item) {
      total += item * item;
      // DOM manipulation to make it take longer and to see progress
      var node = document.createElement("div");
      node.innerHTML = "Async temp value = " + total;
      document.body.appendChild(node);                
   }

   // Let the caller know what the result is when iteration is finished
   function onFinish() {
      callback(total);
   }

   task(squareAndAdd, list, onFinish);

}

var list = [];
for (var i = 0; i < 100000; i++) {
   list.push(Math.random());
}

sumOfSquaresAsync(list, function(total) {
    console.log("Sum of Squares is " + total);        
})

【讨论】:

    【解决方案3】:

    如果您的目标是抑制“Kill-Wait”消息作为对慢速 JavaScript 的快速临时修复,那么解决方案是在 Google Chrome 中打开工具/开发者工具,并在浏览时将其保持打开并最小化在桌面某处。

    【讨论】:

      猜你喜欢
      • 2019-10-14
      • 1970-01-01
      • 2012-10-19
      • 2011-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-06
      • 1970-01-01
      相关资源
      最近更新 更多