JavaScript setTimeout () замедляется при большой нагрузке - PullRequest
5 голосов
/ 31 июля 2009

Я создал скрипт, который затеняет цвет фона элемента. Я использую setTimeout () для постепенного изменения цвета каждые 5 мс. Сценарий прекрасно работает, если я просто замираю фоновым цветом одной вещи за раз, но если у меня есть, скажем, 50 элементов, я замираю сразу, скорость намного ниже 5 мс из-за одновременный запуск setTimeout (). Например, затухание, которое обычно должно выполняться за 1 секунду, может занять 30 секунд, если я замирал 50 элементов одновременно.

Есть идеи, как мне это преодолеть?

Вот сценарий на случай, если у кого-то есть идеи:

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);

Ответы [ 3 ]

11 голосов
/ 31 июля 2009

Вот статья от Google, где автор обсуждает их работу над таймерами для Gmail. Они обнаружили, что наличие одного высокочастотного таймера было быстрее, чем использование нескольких таймеров, если они использовали тяжелый и быстрый таймер.

Вы можете иметь один таймер, который срабатывает каждые 5 мс, и добавлять все ваши элементы, которые должны быть закрашены, в структуру данных, которая отслеживает, где они находятся в процессе замирания. Затем ваш таймер может просматривать этот список и выполнять следующее постепенное изменение для каждого элемента при каждом его срабатывании.

С другой стороны, вы пытались использовать библиотеку, такую ​​как Mootools или JQuery , вместо того, чтобы использовать собственную анимационную среду? Их разработчики приложили много усилий для оптимизации этих видов операций.

4 голосов
/ 31 июля 2009

Прежде всего, ваш скрипт не учитывает, что минимальное время ожидания обычно составляет 10-15 мс в зависимости от браузера. Вы можете увидеть мой пост на эту тему . Внутри вы найдете таблицу для популярных браузеров и ссылку на программу, которая измеряет ее, чтобы вы могли проверить претензию самостоятельно. Извините, но повторения каждые 5 мс - это желаемое за действительное.

Во-вторых, таймеры не являются прерываниями. В них нет волшебства & mdash; они не могут прерывать то, что работает в браузере, и выполнять свою полезную нагрузку. Вместо этого они будут отложены до тех пор, пока не завершится работающий код и браузер не вернет управление и возможность запуска таймеров. Затухание 50 элементов занимает время, и я уверен, что оно больше 5 мс, особенно если вы принимаете во внимание всю отложенную модель браузера: вы обновляете DOM, и браузер обновляет свое визуальное представление & hellip; в какой-то момент времени.

Хочу закончить на положительной ноте:

  • Вместо того чтобы исчезать из 50 отдельных элементов, попробуйте сгруппировать их и затемнить их родительский элемент & mdash; это может быть быстрее.
  • Будьте более креативными в пользовательском интерфейсе. Попробуйте найти решение, которое не требует одновременного исчезновения множества независимых элементов.
  • Всегда проверяйте правильность исходных допущений, прежде чем строить вокруг них.
  • Если можете, попробуйте использовать современные браузеры. По моему личному опыту, Google Chrome отлично справляется с таймерами, а его движок JavaScript (V8) работает очень быстро.
0 голосов
/ 31 июля 2009

В дополнение к другим ответам, вот отличная статья Джона Резига о таймерах: http://ejohn.org/blog/how-javascript-timers-work/

...