setTimeout или setInterval? - PullRequest
       76

setTimeout или setInterval?

722 голосов
/ 08 апреля 2009

Насколько я могу судить, эти две части JavaScript ведут себя одинаково:

Вариант A:

function myTimeoutFunction()
{
    doStuff();
    setTimeout(myTimeoutFunction, 1000);
}

myTimeoutFunction();

Вариант B:

function myTimeoutFunction()
{
    doStuff();
}

myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);

Есть ли разница между использованием setTimeout и setInterval ?

Ответы [ 17 ]

637 голосов
/ 09 апреля 2009

Есть ли разница?

Да. Тайм-аут выполняется определенное количество времени после вызова setTimeout (); Интервал выполняется через определенное время после срабатывания предыдущего интервала.

Вы заметите разницу, если ваша функция doStuff () займет некоторое время для выполнения. Например, если мы представляем вызов setTimeout / setInterval с ., запуск тайм-аута / интервала с * и выполнение кода JavaScript с [-----], временные шкалы выглядят следующим образом:

Timeout:

.    *  .    *  .    *  .    *  .
     [--]    [--]    [--]    [--]

Interval:

.    *    *    *    *    *    *
     [--] [--] [--] [--] [--] [--]

Следующая сложность заключается в том, что интервал срабатывает, пока JavaScript уже занят чем-то (например, обработкой предыдущего интервала). В этом случае интервал запоминается и происходит, как только предыдущий обработчик завершает работу и возвращает управление браузеру. Так, например, для процесса doStuff (), который иногда короткий ([-]), а иногда длинный ([-----]):

.    *    *    •    *    •    *    *
     [-]  [-----][-][-----][-][-]  [-]

• представляет интервал срабатывания, который не смог выполнить свой код сразу, а вместо этого был переведен в режим ожидания.

Таким образом, интервалы пытаются «наверстать», чтобы вернуться по расписанию. Но они не стоят в очереди друг над другом: за интервал может быть только одно ожидание выполнения. (Если они все встанут в очередь, браузер получит постоянно расширяющийся список невыполненных казней!)

.    *    •    •    x    •    •    x
     [------][------][------][------]

x представляет интервал срабатывания, который не может быть выполнен или отложен, поэтому вместо этого он был отброшен.

Если функция doStuff () обычно выполняется дольше, чем установленный для нее интервал, браузер потребляет 100% ресурсов ЦП, пытаясь ее обслуживать, и может стать менее отзывчивым.

Что вы используете и почему?

Chained-Timeout предоставляет гарантированное время свободного времени для браузера; Интервал пытается обеспечить выполнение выполняемой функции как можно ближе к запланированному времени за счет доступности пользовательского интерфейса браузера.

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

Что касается совместимости браузера, setTimeout предшествует setInterval, но все браузеры, которые вы встретите сегодня, поддерживают оба. Последним препятствием на протяжении многих лет был IE Mobile в WinMo <6.5, но, надеюсь, это уже позади. </p>

630 голосов
/ 08 апреля 2009

Они, по сути, пытаются сделать то же самое, но подход setInterval будет более точным, чем подход setTimeout, поскольку setTimeout ждет 1000 мс, запускает функцию и затем устанавливает другое время ожидания. Таким образом, период ожидания на самом деле немного больше 1000 мс (или намного больше, если выполнение вашей функции занимает много времени).

Хотя можно подумать, что setInterval будет выполнять точно каждые 1000 мс, важно отметить, что setInterval также будет задерживать, поскольку JavaScript не является многопоточным языком, что означает, что - если выполняются другие части скрипта - интервал должен ждать, пока это не закончится.

В этой скрипке вы можете четко видеть, что тайм-аут будет отставать, в то время как интервал почти все время составляет почти 1 вызов / секунду (что пытается сделать сценарий). Если вы измените переменную скорости в верхней части на что-то маленькое, например, 20 (это означает, что она будет пытаться запускаться 50 раз в секунду), интервал никогда не достигнет в среднем 50 итераций в секунду.

Задержка почти всегда незначительна, но если вы программируете что-то действительно точное, вам следует воспользоваться самонастраивающимся таймером (который по сути является таймером на основе времени ожидания, который постоянно настраивается на задержка его создания)

85 голосов
/ 14 августа 2013

setInterval ()

setInterval() - это метод выполнения кода на основе временного интервала, который имеет собственную возможность многократного запуска указанного сценария при достижении интервала. Он должен не быть вложенным в функцию обратного вызова автором сценария, чтобы сделать его цикличным, поскольку по умолчанию он зацикливается . Он будет продолжать стрелять с интервалом, пока вы не позвоните clearInterval().

Если вы хотите зациклить код для анимации или на такте, используйте setInterval().

function doStuff() {
    alert("run your code here when time interval is reached");
}
var myTimer = setInterval(doStuff, 5000);

SetTimeout ()

setTimeout() - это метод выполнения кода на основе времени, который будет выполнять сценарий только один раз при достижении интервала. Он будет не повторяться снова, если вы не включите его в цикл сценария, вложив объект setTimeout() в функцию, которую он вызывает для запуска. Если он настроен на петлю, он будет продолжать стрелять с интервалом, пока вы не позвоните clearTimeout().

function doStuff() {
    alert("run your code here when time interval is reached");
}
var myTimer = setTimeout(doStuff, 5000);

Если вы хотите, чтобы что-то произошло один раз по истечении указанного периода времени, используйте setTimeout(). Это потому, что он выполняется только один раз, когда достигается указанный интервал.

41 голосов
/ 08 апреля 2009

setInterval облегчает отмену будущего выполнения вашего кода. Если вы используете setTimeout, вы должны отслеживать идентификатор таймера на случай, если вы захотите отменить его позже.

var timerId = null;
function myTimeoutFunction()
{
    doStuff();
    timerId = setTimeout(myTimeoutFunction, 1000);
}

myTimeoutFunction();

// later on...
clearTimeout(timerId);

против

function myTimeoutFunction()
{
    doStuff();
}

myTimeoutFunction();
var timerId = setInterval(myTimeoutFunction, 1000);

// later on...
clearInterval(timerId);
21 голосов
/ 08 апреля 2009

Я считаю, что метод setTimeout проще в использовании, если вы хотите отменить тайм-аут:

function myTimeoutFunction() {
   doStuff();
   if (stillrunning) {
      setTimeout(myTimeoutFunction, 1000);
   }
}

myTimeoutFunction();

Кроме того, если что-то пойдет не так в функции, оно просто перестанет повторяться при первой ошибке, а не повторяется каждую секунду.

16 голосов
/ 11 января 2014

Разница в их целях.

setInterval()
   -> executes a function, over and over again, at specified time intervals  

setTimeout()
   -> executes a function, once, after waiting a specified number of milliseconds

Это так просто

Более подробная информация здесь http://javascript.info/tutorial/settimeout-setinterval

12 голосов
/ 26 апреля 2014

Когда вы запускаете какую-то функцию внутри setInterval, которая работает больше времени, чем тайм-аут-> браузер застрянет.

- Например, doStuff () занимает 1500 сек. чтобы выполнить, и вы делаете: setInterval (doStuff, 1000);
1) Браузер запускается doStuff () , что занимает 1,5 сек. быть выполненным;
2) Через ~ 1 секунду он снова пытается запустить doStuff () . Но предыдущий doStuff () все еще выполняется ->, поэтому браузер добавляет этот запуск в очередь (запуск после первого выполнения).
3,4, ..) То же добавление в очередь выполнения для следующих итераций, но doStuff () из предыдущего все еще выполняется ...
В результате браузер завис.

Чтобы предотвратить такое поведение, лучше всего запустить setTimeout внутри setTimeout для эмуляции setInterval .
Чтобы исправить тайм-ауты между вызовами setTimeout, вы можете использовать самокорректирующуюся альтернативу методу JavaScript setInterval .

7 голосов
/ 08 апреля 2009

Я использую setTimeout.

Видимо, разница заключается в том, что setTimeout вызывает метод один раз, setInterval вызывает его повторно.

Вот хорошая статья, объясняющая разницу: Учебное пособие: таймеры JavaScript с setTimeout и setInterval

5 голосов
/ 26 ноября 2012

Я сделал простой тест setInterval(func, milisec), потому что мне было любопытно, что происходит, когда потребление времени функции больше, чем длительность интервала.

setInterval будет обычно планировать следующую итерацию сразу после start предыдущей итерации, , если функция все еще продолжается . Если это так, setInterval будет ждать до завершения функции. Как только это происходит, функция сразу же запускается снова - больше нет ожидания следующей итерации в соответствии с расписанием (как это было бы в условиях без превышения времени функцией). Также нет ситуации с параллельными итерациями.

Я проверял это на Chrome v23. Я надеюсь, что это детерминированная реализация во всех современных браузерах.

window.setInterval(function(start) {
    console.log('fired: ' + (new Date().getTime() - start));
    wait();
  }, 1000, new Date().getTime());

Вывод на консоль:

fired: 1000    + ~2500 ajax call -.
fired: 3522    <------------------'
fired: 6032
fired: 8540
fired: 11048

Функция wait - это просто помощник по блокировке потоков - синхронный вызов ajax, который занимает ровно 2500 миллисекунд обработки на стороне сервера:

function wait() {
    $.ajax({
        url: "...",
        async: false
    });
}
3 голосов
/ 08 апреля 2009

И setInterval, и setTimeout возвращают идентификатор таймера, который можно использовать для отмены выполнения, то есть до запуска тайм-аутов. Для отмены звоните либо clearInterval, либо clearTimeout следующим образом:

var timeoutId = setTimeout(someFunction, 1000);
clearTimeout(timeoutId);
var intervalId = setInterval(someFunction, 1000),
clearInterval(intervalId);

Кроме того, тайм-ауты автоматически отменяются, когда вы покидаете страницу или закрываете окно браузера.

...