如何防止慢速脚本警告并强制浏览器继续运行脚本直到完成?

时间:2011-07-06 14:42:58

标签: javascript


更新(2013年7月5日):

自从我最初提出这个问题以来,我学到了很多东西。在下面的一条评论中,有人建议我重新处理任务并找到解决问题的方法,而不会有阻止UI的风险。我说这是不可能的,函数必须按原样运行。我实际上并不记得我试图通过该功能完成的任务,但我确信评论者是对的,我错了。如果您偶然发现这个问题并且处于与我相似的情况,那么请认真考虑您的方法存在缺陷的可能性。

您可能还想查看web workers

Here is where you can expect them to work.


原始问题:

我不会过分具体地解决我的问题,而是保持这种通用性,以便其他偶然发现它的人可以发现它很有用。

我有一个接受一个参数的函数,一个字符串。如果字符串很短,则函数运行正常并及时完成。但是,如果传入的字符串太长,脚本会运行一段时间,那么最终会超时并返回浏览器的慢脚本对话框,允许用户终止脚本。

我想防止这种情况发生,以便脚本可以继续到它的终点。

如何做到这一点?

旁注:如果我能够正常工作,我还想创建一个状态栏,类似于加载gmail时看到的状态栏,这样用户就知道事情正在发生。

谢谢!

5 个答案:

答案 0 :(得分:6)

您可以尝试不要完全阻止用户界面,并使用setTimeout“在另一个主题中”运行。

window.setTimeout(function() { ... code ... }, 0);

我说“在另一个线程中”因为JS中没有真正的多线程,而here是关于它的好文章


编辑:(使这个答案与网络技术保持同步)

您还可以使用HTML 5 Web Workers ,具体取决于browser you are targeting

答案 1 :(得分:5)

无法通过脚本在任何浏览器中禁用该行为。想象一下影响,禁用该功能并调用while(1)。非常糟糕。

您可以创建阻止浏览器“太久”的代码。如果最佳实践模式有一吨。我总是建议尝试将你的algorythm分解成更小的块。将它与失控定时器和循环相结合,确保任何操作的运行时间不超过100毫秒(例如)。

var sequence = ['foo', 'bar', 'baz', 'base', 'ball', 'hello', 'world', '100k more'],
    start = Date.now();

setTimeout(function _worker() {
    do {
       var element = sequence.shift();
       // do something with element
    } while( sequence.length && (Date.now() - start < 100) );

    if( sequence.length )
        setTimeout(_worker, 25);
}, 25);

答案 2 :(得分:3)

除非您的代码确实是恶意或恶意的,否则这几乎总是在IE 9及更低版本中发生,当无辜的脚本具有执行时间太长的循环或者对慢速服务器进行AJAX调用或者有大量数据时退回,超过允许的限制。

因此,如果真的困扰他们,您可以让您的用户在此处关注此问题的Microsoft官方修复:   http://support.microsoft.com/kb/175500 如果他们运行此 Microsoft FixIT修补程序,则会将其默认的 MaxScriptStatements 从默认的5,000,000个语句增加到允许的最大值(由十六进制值 0xFFFFFF 表示,这是等于4,294,967,295总执行声明)它应该解决问题,除非我提到,代码特别糟糕或需要重构。

总之,您的选择是:

  1. 最佳解决方案 - fix your script ...在N次执行后分解循环和/或停止递归,并确保AJAX请求尽可能asynchronous not synchronous,尤其是在循环中

  2. 替代黑客 - 使用 HTML5 WebWorkers ,但最好先使用WebWorker detection查看your browser是否支持它们,并使用类似的WebWorker填充程序库如果不支持,则thisthis

  3. 平庸的黑客攻击 - setTimeout ,真正的script execution Timer并打破循环迭代,可能会有边缘情况导致更严重的问题......

  4. 糟糕的黑客 - ActiveX registry writing ,最好使用正确的browser detection加上feature detection

  5. 最佳解决方法 - Microsoft FixIT patch ,如果只是一小部分用户,请将技术支持发送到官方Microsoft FixIT页面(或自己动手)可靠地添加适当的注册表项以增加脚本执行次数

答案 3 :(得分:1)

你可以尝试一些事情:

  1. 使用setTimeout
  2. 异步运行函数
  3. 让你的函数不时地睡眠,以便长时间停止阻止UI(如果它很慢,那就让它运行一段时间吧)
  4. 使用javascript worker替代setTimeout,这里有一些快速的Google搜索:http://ejohn.org/blog/web-workers/

答案 4 :(得分:1)

删除警告:

function setMaxScriptStatements(){

var WshShell = new ActiveXObject("WScript.Shell");
    WshShell.RegWrite ("HKCU\\Software\\Microsoft\\Internet Explorer\\Styles\\MaxScriptStatements", 1107296255, "REG_DWORD");
}