JavaScript setTimeout() замедляется при большой нагрузке

StackOverflow https://stackoverflow.com/questions/1209173

  •  05-07-2019
  •  | 
  •  

Вопрос

Я создал скрипт, который изменяет цвет фона элемента.Я использую 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);
Это было полезно?

Решение

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

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

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

Другие советы

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

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

Я хочу закончить на позитивной ноте:

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top