【问题标题】:How do I prevent the slow script warning and force the browser to continue running script until it's finished?如何防止脚本缓慢警告并强制浏览器继续运行脚本直到它完成?
【发布时间】:2011-07-06 14:42:58
【问题描述】:

更新(2013 年 7 月 5 日):

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

您可能还想查看web workers

Here is where you can expect them to work.


原问题:

我不会对我的问题过于具体,而是保持这个通用性,以便其他偶然发现它的人会发现它很有用。

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

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

如何做到这一点?

附注:如果我能做到这一点,我还想制作一个状态栏,类似于您在加载 gmail 时看到的状态栏,以便用户知道正在发生的事情。

谢谢!

【问题讨论】:

  • 我认为你需要修复你的功能,这样就不会花这么长时间。
  • 那么你需要在浏览器以外的地方进行。也许您可以将该功能移植到您要使用的任何服务器端语言。
  • 我会先尝试felipe 的建议,如果必须,我会将其传递给服务器。感谢您的提示。

标签: javascript


【解决方案1】:

您可以尝试不完全阻止 UI,并使用 setTimeout 使其“在另一个线程中”运行。

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

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


编辑:(使用网络技术使这个答案更加最新)

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

【讨论】:

  • 所以我目前使用for循环来解析字符串中的每个字符。我将用手动计数器和 setTimeout 代替它,看看会发生什么。等等……这就是你的建议吗?
  • 您在这样做时只需要小心范围问题 :)
  • 毫无疑问。感谢帮助。我会让你知道会发生什么。
  • 这可以防止慢速脚本警告。它还允许我添加进度条。 setInterval 比传统的 forloop 慢得多,所以这种折衷是不值得的。
【解决方案2】:

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

您可以自己编写代码不会阻止浏览器“太长时间”。有很多最佳实践模式。我总是建议尝试将你的算法分解成更小的块。将其与失控计时器和循环结合使用,以确保任何操作的运行时间不会超过 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);

【讨论】:

    【解决方案3】:

    除非您的代码非常糟糕或恶意,否则这几乎总是仅在 IE 9 及更低版本中发生被退回并且超过了允许的限制。

    因此,如果确实让用户感到困扰,您可以让您的用户在此处关注 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. 替代 hack - 使用 HTML5 WebWorkers,但最好先使用 WebWorker detection 以查看 your browser 是否支持它们,并使用 WebWorker shim 库,如 this 或 @987654328 @如果不支持

    3. 平庸的 hack - setTimeout 使用真正的 script execution Timer 并将循环分解为迭代,可能会出现导致更严重问题的极端情况...

    4. 可怕的 hack - ActiveX registry writing,最好使用正确的browser detection 加上feature detection

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

    【讨论】:

      【解决方案4】:

      你可以尝试几件事:

      1. 使用 setTimeout 异步运行函数
      2. 让您的函数时不时地休眠以停止长时间阻塞 UI(见鬼,如果它那么慢,让它运行更长时间)
      3. 使用 javascript worker 作为 setTimeout 的替代,这里有一些快速的谷歌搜索:http://ejohn.org/blog/web-workers/

      【讨论】:

        【解决方案5】:

        要删除警告:

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

        【讨论】:

          猜你喜欢
          • 2022-10-14
          • 2013-08-26
          • 1970-01-01
          • 1970-01-01
          • 2013-12-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-22
          相关资源
          最近更新 更多