SetTimeout или setInterval?

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

Вариант A:

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

myTimeoutFunction();

Вариант B:

function myTimeoutFunction()
{
    doStuff();
}

myTimeoutFunction();
setInterval(myTimeoutFunction, 1000);

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

Ответ 1

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

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

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

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

Ответ 2

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

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

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

Timeout:

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

Interval:

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

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

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

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

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

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

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

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

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

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

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

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

Ответ 3

setInterval()

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

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

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

SetTimeout()

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

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

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

Ответ 4

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

Ответ 5

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

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

myTimeoutFunction();

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

Ответ 6

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

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

Ответ 7

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

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

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

Ответ 9

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

Ответ 10

Я сделал простой тест 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
    });
}

Ответ 11

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

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

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

Ответ 12

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

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

Ответ 13

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

Ответ 14

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

enter image description here

Ответ 15

Вы можете проверить ответ 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);
});

Ответ 16

Ваш код будет иметь разные исполнения, а в некоторых проектах, таких как онлайн-игры, это неприемлемо. Во-первых, что вы должны сделать, чтобы ваш код работал с одинаковыми 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 мс, и результат будет стабильным.

Ответ 17

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

Ответ 18

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

Параметры A

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

Разве это не так?

Ответ 19

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

var i = 0; 
//The parameter leaks stack memory
function tickFunction(param) 
{ 
    //The following array leaks heap memory
    var heapLeakArray = ["sdsadsasad", "dsadsadsasa", "dsadsadsa"]; 
    //The following call leaks stack memory
    setTimeout(function(){tickFunction(++param);}, 10);
}

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

Ответ 20

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

Попробуйте использовать эти коды после таймаута отсчета секунд:

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

а затем попробуйте

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

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