【问题标题】:JavaScript setTimeout() slows down under heavy loadJavaScript setTimeout() 在重负载下变慢
【发布时间】:2009-07-30 20:33:04
【问题描述】:

我创建了一个淡化元素背景颜色的脚本。我使用 setTimeout() 每 5 毫秒对颜色进行一次增量更改。如果我一次只淡化一件事的背景颜色,该脚本效果很好,但如果我有 50 个元素,我会一次全部淡化,速度比 5 毫秒慢得多,因为所有同时运行的 setTimeout()s。例如,如果我一次淡化 50 个元素,通常应该在 1 秒内执行的淡入淡出可能需要 30 秒。

有什么办法可以克服这个问题吗?

这是脚本以防万一有人有想法:

function fadeBackground(elementId, start, end, time) {
    var iterations = Math.round(time / 5);

    var step = new Array(3);

    step[0] = (end[0] - start[0]) / iterations;
    step[1] = (end[1] - start[1]) / iterations;
    step[2] = (end[2] - start[2]) / iterations;

    stepFade(elementId, start, step, end, iterations);
}

function stepFade(elementId, cur, step, end, iterationsLeft) {
    iterationsLeft--;

    document.getElementById(elementId).style.backgroundColor
        = "rgb(" + cur[0] + "," + cur[1] + "," + cur[2] + ")";

    cur[0] = Math.round(end[0] - step[0] * iterationsLeft);
    cur[1] = Math.round(end[1] - step[1] * iterationsLeft);
    cur[2] = Math.round(end[2] - step[2] * iterationsLeft);

    if (iterationsLeft > 1) {
        setTimeout(function() {
            stepFade(elementId, cur, step, end, iterationsLeft);
        }, 5);
    }
    else {
        document.getElementById(elementId).style.backgroundColor 
            = "rgb(" + end[0] + "," + end[1] + "," + end[2] + ")";
    }
}

它是这样使用的:

fadeBackground("myList", [98,180,232], [255,255,255], 1000);

【问题讨论】:

    标签: javascript settimeout


    【解决方案1】:

    这是来自 Google 的 article,作者在其中讨论了他们在 Gmail 计时器方面的工作。他们发现,如果他们大量快速地使用计时器,那么拥有一个高频计时器比使用多个计时器更快。

    您可以有一个每 5 毫秒触发一次的计时器,并将所有需要淡入淡出的元素添加到一个数据结构中,以跟踪它们在淡入淡出过程中的位置。然后,您的一个计时器可以查看该列表并在每次触发每个元素时对其执行下一次淡入淡出。

    另一方面,您是否尝试过使用像 MootoolsJQuery 这样的库而不是滚动您自己的动画框架?他们的开发人员在优化此类操作方面投入了大量工作。

    【讨论】:

    • 我在想一个计时器可能是要走的路,但我担心必须实施更改。 :) 我实际上决定推出自己的产品,因为我使用 jQuery 来进行 animate() 并且它实际上在大约 10% 的时间里没有褪色。不幸的是,这是一个不可接受的错误率。我会看看这篇文章。非常感谢!
    • 嘿。 Stackoverflow 也有“动画失败”的问题。
    【解决方案2】:

    首先,您的脚本没有考虑到最小超时通常为 10-15 毫秒,具体取决于浏览器。你可以看到my post on this topic。在里面你会找到一个流行浏览器的表格和一个衡量它的程序的链接,所以你可以自己验证声明。很抱歉,每 5 毫秒迭代一次是一厢情愿的想法。

    其次,定时器不是中断。它们没有魔法——它们不能中断浏览器中正在运行的任何东西并执行它们的有效负载。相反,它们将被推迟到运行代码完成并且浏览器重新获得控制权和运行计时器的能力。淡化 50 个元素需要时间,我敢打赌它超过 5 毫秒,特别是如果你考虑到浏览器的整个延迟模型:你更新 DOM,浏览器会在某个时间点更新它的视觉表示。

    我想以积极的态度结束:

    • 与其淡出 50 个单独的元素,不如尝试将它们分组并淡化它们的父元素——这样会更快。
    • 在 UI 方面更具创意。试着想出一个解决方案,它不需要一次淡出很多独立的元素。
    • 在围绕它们进行设计之前,请始终验证您的背景假设是否正确。
    • 如果可以,请尝试针对现代浏览器。以我个人的经验来看,谷歌浏览器在定时器方面做得非常好,它的 JavaScript 引擎 (V8) 速度非常快。

    【讨论】:

      猜你喜欢
      • 2016-03-03
      • 2017-12-01
      • 1970-01-01
      • 2021-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-08
      相关资源
      最近更新 更多