setTimeout или setInterval? - PullRequest
       75

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 ]

3 голосов
/ 24 декабря 2016

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

3 голосов
/ 27 января 2015

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

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

2 голосов
/ 18 ноября 2014

Вы можете проверить ответ 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);
});
2 голосов
/ 18 октября 2011

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

1 голос
/ 26 мая 2014

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

1 голос
/ 05 января 2014

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

enter image description here

0 голосов
/ 17 апреля 2013

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

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

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

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

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

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

...