Как запустить и остановить/приостановить setInterval?

Я пытаюсь сделать паузу, а затем воспроизвести цикл setInterval.

После того, как я остановил цикл, кнопка «Пуск» в моя попытка не работает :

input = document.getElementById("input");

function start() {
  add = setInterval("input.value++", 1000);
}
start();
<input type="number" id="input" />
<input type="button" onclick="clearInterval(add)" value="stop" />
<input type="button" onclick="start()" value="start" />

Есть ли рабочий способ сделать это?


person Web_Designer    schedule 16.12.2011    source источник
comment
Спасибо @mrtsherman! Используя ваш метод: jsfiddle.net/gEdKM/4   -  person Web_Designer    schedule 17.12.2011
comment
Пожалуйста, если вы собираетесь это использовать, по крайней мере, исправьте свой таймер так, как показывает ответ MДΓΓ БДLL.   -  person Alnitak    schedule 17.12.2011


Ответы (7)


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

JSFiddle заключает ваш код в функцию, поэтому start() не определяется в глобальной области видимости.

введите здесь описание изображения


Мораль этой истории: не используйте встроенные привязки событий. Используйте addEventListener/attachEvent.


Другие примечания:

Пожалуйста, не передавайте строки в setTimeout и setInterval. Это eval в маскировке.

Вместо этого используйте функцию и устройтесь поудобнее с var и пробелом:

var input = document.getElementById("input"),
  add;

function start() {
  add = setInterval(function() {
    input.value++;
  }, 1000);
}

start();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="number" id="input" />
<input type="button" onclick="clearInterval(add)" value="stop" />
<input type="button" onclick="start()" value="start" />

person Matt Ball    schedule 16.12.2011
comment
Ницца. Я не мог понять, почему его скрипка не вела себя. Хорошо знать. +1 - person mrtsherman; 16.12.2011
comment
yup - jsFiddle очень удобен, но вы должны знать, как он работает иначе, чем обычный файл сценария. - person Alnitak; 16.12.2011
comment
@Web_Designer просто использует код в ответе Alnitak, если вы действительно используете jQuery (поскольку ваш вопрос помечен). - person Matt Ball; 17.12.2011

См. рабочую демонстрацию jsFiddle: http://jsfiddle.net/qHL8Z/3/

$(function() {
  var timer = null,
    interval = 1000,
    value = 0;

  $("#start").click(function() {
    if (timer !== null) return;
    timer = setInterval(function() {
      $("#input").val(++value);
    }, interval);
  });

  $("#stop").click(function() {
    clearInterval(timer);
    timer = null
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="number" id="input" />
<input id="stop" type="button" value="stop" />
<input id="start" type="button" value="start" />

person jessegavin    schedule 16.12.2011

Поскольку вы отметили этот jQuery...

Во-первых, поместите идентификаторы на кнопки ввода и удалите встроенные обработчики:

<input type="number" id="input" />
<input type="button" id="stop" value="stop"/>
<input type="button" id="start" value="start"/>

Затем сохраните все свое состояние и функции, инкапсулированные в замыкание:

РЕДАКТИРОВАНИЕ обновлено для более чистой реализации, что также устраняет опасения @Esailija по поводу использования setInterval().

$(function() {
    var timer = null;
    var input = document.getElementById('input');

    function tick() {
        ++input.value;
        start();        // restart the timer
    };

    function start() {  // use a one-off timer
        timer = setTimeout(tick, 1000);
    };

    function stop() {
        clearTimeout(timer);
    };

    $('#start').bind("click", start); // use .on in jQuery 1.7+
    $('#stop').bind("click", stop);

    start();  // if you want it to auto-start
});

Это гарантирует, что ни одна из ваших переменных не попадет в глобальную область видимости и не сможет быть изменена извне.

(Обновлено) рабочая демонстрация на http://jsfiddle.net/alnitak/Q6RhG/

person Alnitak    schedule 16.12.2011
comment
Учитывая, что этот вопрос помечен jquery (что я пропустил), это лучшее решение. - person Matt Ball; 16.12.2011
comment
для справки, здесь проголосовали против, потому что некоторые люди не согласились с некоторыми моими взглядами в другом месте, а не потому, что с ответом что-то не так. - person Alnitak; 17.12.2011
comment
Возможно, вы захотите немного изменить это: jsfiddle.net/mattball/2aSAV. Извините за хромые отрицательные голоса. Это не то, как голосование должно работать. - person Matt Ball; 17.12.2011

add - это локальная переменная, а не глобальная переменная, попробуйте это

var add;
var input = document.getElementById("input");

function start() {
  add = setInterval("input.value++", 1000);
}
start();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="number" id="input" />
<input type="button" onclick="clearInterval(add)" value="stop" />
<input type="button" onclick="start()" value="start" />

person Jazz Man    schedule 16.12.2011
comment
@Web_Designer - это из-за скрипки, а не из-за его кода. См. ответ Мэтта Болла. Тот же код, но теперь работает — jsfiddle.net/gEdKM/4 - person mrtsherman; 16.12.2011
comment
Спасибо @mrtsherman Если бы я мог принять комментарий, я бы принял ваш. Это метод, который я в конечном итоге использую. - person Web_Designer; 17.12.2011
comment
@Web_Designer по-прежнему использует строку вместо функции в setInterval() - person Alnitak; 17.12.2011
comment
@Web_Designer - Альнитак прав. Вы должны использовать ответ Мэтта Болла, а не этот. Я просто указал даунвотеру, что Джазмен этого не заслужил. - person mrtsherman; 17.12.2011
comment
Не могли бы вы, ребята, предоставить демонстрацию ответа @MДΓΓ БДLL? Спасибо! - person Web_Designer; 17.12.2011
comment
@Web_Designer Я обновил свой ответ, чтобы отразить различные комментарии и дать более чистую реализацию. - person Alnitak; 17.12.2011

(function(){
    var i = 0;
    function stop(){
        clearTimeout(i);
    }

    function start(){
        i = setTimeout( timed, 1000 );
    }

    function timed(){
       document.getElementById("input").value++;
       start();
    }

    window.stop = stop;
    window.start = start;
})()

http://jsfiddle.net/TE3Z2/

person Esailija    schedule 16.12.2011
comment
потому что помещать функции в глобальную область видимости и вызывать их из встроенных обработчиков событий оба являются плохой практикой. - person Alnitak; 16.12.2011
comment
Я голосую против по той же причине, которую привел Альнитак. - person jessegavin; 16.12.2011
comment
@Alnitak конечно, но setInterval - одна из худших практик. Я не минусую людей, потому что они этого не считают. Я просто работаю с кодом OP как можно ближе, с удалением самых злостных нарушителей. - person Esailija; 16.12.2011
comment
@Esailija ИМХО для этой цели setInterval() вполне приемлемо. Риск того, что события таймера будут стоять в очереди из-за того, что они не были обслужены, практически незначителен. - person Alnitak; 16.12.2011
comment
@Alnitak, правильно, потому что это единственное, что плохо в setInterval. вздох. Как насчет того факта, что если элементы будут удалены, setInterval будет продолжать вызывать ошибки, если вы не сделаете какой-то избыточный защитный код. вздох. - person Esailija; 16.12.2011
comment
@Esailija, о чем ты? Повторяющийся цикл setTimeout() будет иметь точно такую ​​же гипотетическую проблему. - person Alnitak; 16.12.2011
comment
@Alnitak Нет, не будет, это вызовет одну ошибку, а затем остановится. - person Esailija; 16.12.2011
comment
@Esailija, вы собираете гниды в гипотетической ситуации, которой нет в этом коде. ОВП. - person Alnitak; 16.12.2011

Я использую несколько таймеров таким образом. Это не элегантное решение, но оно работает хорошо.

var timerclass = function () {
    this.initialTime = Date.now();
    var t=this;
    var Timer = setInterval(function(){t.checkTime();}, 1000); //start the timer (goes to function checkTime every 1000ms )
    this.timerstart=false;      
}; //end of constructor

timerclass.prototype.StartTheTimer = function(){    
    this.initialTime = Date.now(); //Time right now
    this.timerstart=true;
};      
    
timerclass.prototype.checkTime= function(){ 
    if(this.timerstart==true)
    {
        var timeDifference = Date.now() - this.initialTime; 
        console.log("Time ms: "+timeDifference);        
   }
};  
    
timerclass.prototype.StopTimer= function(){
    this.timerstart=false;
};      
    
module.exports = timerclass;

Затем в вашем основном коде:

var MyTimerSystem = require(__dirname+'/class.timerclass.js');
var MyFirstTimerObject = new MyTimerSystem(); //First Timer 
var MySecondTimerObject = new MyTimerSystem(); //Second Timer

Остановить таймер(ы):

MyFirstTimerObject.StopTimer(); //Stop First Timer
MySecondTimerObject.StopTimer(); //Stop Second Timer

Снова перезапустите таймер(ы) с 0 мс:

MyFirstTimerObject.StartTheTimer();  //Start or restart the First timer
MySecondTimerObject.StartTheTimer(); //Start or restart the Second timer
person CMP    schedule 24.03.2021

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

person Diodeus - James MacFarlane    schedule 16.12.2011