setTimeout или setInterval?

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

Вариант A:

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

myTimeoutFunction();

Вариант B:

function myTimeoutFunction()
{
    doStuff();
}

myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);

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

19 ответов


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

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

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

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


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

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

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

Timeout:

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

Interval:

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

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

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

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

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

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

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

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

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

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

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

С точки зрения совместимости браузера, setTimeout предшествует setInterval, но все браузеры, которые вы встретите сегодня, поддерживают оба. Последним отставшим в течение многих лет был IE Mobile в WinMo


setInterval ()

setInterval() - это метод выполнения кода на основе временного интервала, который имеет собственную возможность многократно запускать указанный скрипт при достижении интервала. Он должен!--12-->не быть вложенным в его функцию обратного вызова автором сценария, чтобы сделать его циклом, так как он петли по умолчанию. Он будет продолжать стрелять в промежутке, если вы не позвоните 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(). Это связано с тем, что он выполняется только один раз при достижении указанного интервала.


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

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

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

myTimeoutFunction();

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


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

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


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

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

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


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

видимо, разница в функции setTimeout раз вызывает метод, метод setInterval вызывает его repeatdly.

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


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


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

setInterval будет вообще запланировать следующую итерацию сразу после старт предыдущей итерации,если функция все еще продолжается. Если так, то 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
    });
}

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

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

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


чтобы посмотреть на это немного по-другому: setInterval гарантирует, что код запускается на каждом заданном интервале (т. е. 1000 мс или сколько вы указываете), в то время как setTimeout устанавливает время, когда он "ждет, пока" он запускает код. И поскольку для запуска кода требуется дополнительные миллисекунды, он добавляет до 1000 мс и, таким образом, setTimeout запускается снова в неточное время (более 1000 мс).

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


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


разница очевидна в консоли:

enter image description here


вы можете проверить ответ bobince самостоятельно при запуске следующего javascript или проверить это JSFiddle

<div id="timeout"></div>
<div id="interval"></div>

var timeout = 0;
var interval = 0;

function doTimeout(){
    $('#timeout').html(timeout);
    timeout++;
    setTimeout(doTimeout, 1);
}

function doInterval(){
    $('#interval').html(interval);
    interval++;
}

$(function(){
    doTimeout();
    doInterval();
    setInterval(doInterval, 1);
});

ваш код будет иметь разные intevals выполнения, а в некоторых проектах, таких как онлайн-игры, это неприемлемо. Во-первых, что вы должны сделать, чтобы ваш код работал с теми же intevals, вы должны изменить "myTimeoutFunction" на это:

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

после этого изменения, он будет равен

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

но у вас все равно не будет стабильного результата, потому что JS однопоточный. На данный момент, если поток JS будет чем-то занят, он не сможет выполнить ваш функция обратного вызова, и выполнение будет отложено на 2-3 мс. У вас есть 60 исполнений в секунду, и каждый раз, когда у вас есть случайная задержка 1-3 сек, это будет абсолютно неприемлемо (через одну минуту это будет задержка около 7200 МС), и я могу посоветовать использовать что-то вроде этого:

    function Timer(clb, timeout) {
        this.clb = clb;
        this.timeout = timeout;
        this.stopTimeout = null;
        this.precision = -1;
    }

    Timer.prototype.start = function() {
        var me = this;
        var now = new Date();
        if(me.precision === -1) {
            me.precision = now.getTime();
        }
        me.stopTimeout = setTimeout(function(){
            me.start()
        }, me.precision - now.getTime() + me.timeout);
        me.precision += me.timeout;
        me.clb();
    };

    Timer.prototype.stop = function() {
        clearTimeout(this.stopTimeout);
        this.precision = -1;
    };

    function myTimeoutFunction()
    {
        doStuff();
    }

    var timer = new Timer(myTimeoutFunction, 1000);
    timer.start();

этот код гарантирует стабильный период выполнения. Даже поток будет занят, и ваш код будет выполнен через 1005 МС, в следующий раз он будет иметь тайм-аут для 995 МС и результат будет стабильно.


просто добавляя к тому, что уже было сказано, но версия setTimeout кода также достигнет Maximum call stack size который остановит его от функционирования. Поскольку нет базового случая для рекурсивной функции, чтобы остановиться, поэтому вы не можете ее запустить навсегда.


вероятно, лучше заменить первую функцию на эту

Опции A'

function myTimeoutFunction()
{
     setTimeout(myTimeoutFunction, 1000);// At first 
     doStuff();
}
myTimeoutFunction();

не так ли ?


Я думаю SetInterval и SetTimeout разные. SetInterval выполняет блок в соответствии с установленным временем, в то время как,SetTimeout выполняет блок программного кода один раз.

попробуйте этот набор кодов после тайм-аута обратного отсчета секунд:

setInterval(function(e){
    alert('Ugbana Kelvin');
}, 2000);

а потом попробовать

setTimeout(function(e){
    alert('Ugbana Kelvin');
}, 2000);

вы можете увидеть разницу для себя.