JavaScript执行会暂时挂起页面

时间:2012-09-14 06:58:54

标签: javascript jquery hang

我有一个大量使用 jQuery / JavaScript 的网络应用程序。它在内存中包含一个大型数组,用户可以通过键入文本框来过滤它。

问题:当过滤算法运行时,应用程序变得无法响应,浏览器甚至可能会询问用户是否让脚本继续运行。

最理想的情况是,我希望过滤器功能在单独的线程中运行,以避免无响应。这有可能吗?或者,我想展示一个旋转沙漏或类似的东西,但浏览器似乎无法在运行繁重的脚本时显示动画GIF。

攻击问题的最佳方法是什么?

3 个答案:

答案 0 :(得分:3)

浏览器在主事件处理线程中执行脚本。这意味着任何长时间运行的脚本都可以保留浏览器队列。

您应该将过滤器逻辑拆分为块并在timeout回调上运行它们。您可以在执行之间使用0毫秒的间隙。 0 milli只是对浏览器的建议,但浏览器将使用后续回调之间的差距来清除其事件队列。超时通常是在浏览器环境中应该运行多长时间的脚本以防止页面“挂起”。

答案 1 :(得分:2)

这类工作是Web Workers的设计目标,支持是patchy, but improving

答案 2 :(得分:2)

扩展我之前的评论,假设您正在处理数组,那么您可能正在使用for循环。您可以轻松地重构一个简单的for循环以使用setTimeout(),以便将工作分解为块,并且浏览器有机会处理每个块之间的屏幕绘制和用户交互。简单的例子:

// Generic function to execute a callback a given number
// of times with a given delay between each execution
function timeoutLoop(fn, startIndex, endIndex, delay) {
    function doIteration() {
        if (startIndex < endIndex){
            fn(startIndex++);
            setTimeout(doIteration, delay);
        }
    }
    doIteration();
}

// pass your function as callback
timeoutLoop(function(i) {
   // current iteration processing here, use i if needed;
}, 0, 100, 0);

演示:http://jsfiddle.net/nnnnnn/LeZxM/1/

这只是我拼凑在一起展示一般想法的东西,但显然它可以通过各种方式进行扩展,例如,您可能希望向chunkSize添加timeoutLoop()参数来说明有多少循环在每次超时中进行迭​​代(在fn()的调用周围添加传统循环)等等。