Прекратить вызов setInterval в JavaScript


1400

Я использую setInterval(fname, 10000);для вызова функции каждые 10 секунд в JavaScript. Можно ли перестать называть это на каком-то событии?

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

Ответы:


2160

setInterval()возвращает идентификатор интервала, который вы можете передать clearInterval():

var refreshIntervalId = setInterval(fname, 10000);

/* later */
clearInterval(refreshIntervalId);

Смотрите документы для setInterval()и clearInterval().


42
Как вы можете запустить его снова после остановки с 'clearInterval ()'? Если я попытаюсь перезапустить его, я получу 2 раза запущенный setInterval.
Дан

8
Я тоже Каждый раз, когда я хочу использовать SetInterval (MyFunction, 4000); это становится все быстрее и быстрее, каждый раз в 2 раза быстрее :( как я могу перезапустить setinterval ??
Алиреза Масали

14
SetInterval () не меняет скорость, которую вы передаете. Если то, что он делает, ускоряется при каждом вызове SetInterval (), то у вас есть несколько таймеров, которые работают одновременно, и вам следует открыть новый вопрос.
EpicVoyage

29
Убедитесь, что вы действительно останавливаете это. Из-за изменяемой области видимости у вас может не быть права на вызов clearInterval. Я использовал window.refreshIntervalIdвместо локальной переменной, и она прекрасно работает!
OSA

2
Я начал прикреплять дескриптор setInterval к ​​связанному с ним элементу (когда это уместно): $('foo').data('interval', setInterval(fn, 100));и затем очищать его, clearInterval($('foo').data('interval'));я уверен, что есть и не-jQuery способ сделать это тоже.
Майкл - Где Клэй Ширки

105

Если вы установите возвращаемое значение setIntervalпеременной, вы можете clearIntervalостановить ее.

var myTimer = setInterval(...);
clearInterval(myTimer);

Я не вижу разницы между этим и ответом Джона
Bobtroopo

51

Вы можете установить новую переменную и увеличивать ее на ++ (подсчитывать единицу) каждый раз, когда она запускается, затем я использую условный оператор для ее завершения:

var intervalId = null;
var varCounter = 0;
var varName = function(){
     if(varCounter <= 10) {
          varCounter++;
          /* your code goes here */
     } else {
          clearInterval(intervalId);
     }
};

$(document).ready(function(){
     intervalId = setInterval(varName, 10000);
});

Я надеюсь, что это помогает и это правильно.


3
Я был удивлен, узнав, что это работает clearInterval(varName);. Я ожидал, clearIntervalчто не будет работать, когда передал имя функции, я думал, что требуется идентификатор интервала. Я предполагаю, что это может работать, только если у вас есть именованная функция, так как вы не можете передать анонимную функцию как переменную внутри себя.
Патрик М

31
На самом деле я думаю, что это не работает. Код перестает выполняться из-за ограничения счетчика, но интервал продолжает срабатывать varName (). Попробуйте записать что-нибудь после clearInterval () (внутри предложения else), и вы увидите, что оно пишется вечно.
Рафаэль Оливейра

5
Так много голосов за то, что не работает, иногда я не понимаю людей на SO: P
Stranded Kid

2
$(document).ready(function(){ });это JQuery, поэтому он не работает Это должно быть упомянуто по крайней мере.
паддотк

4
@OMGrant, в дополнение к примеру, который не работает, у вас есть переменная с именем varName, которая хранит безымянную функцию - что ?? Вы должны изменить или снять этот ответ, ИМХО.
Дин Рэдклифф,

13

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

Некоторые архитектурные соображения:

Пожалуйста, не используйте переменные "scope-less". Самый безопасный способ - использовать атрибут объекта DOM. Самым простым местом был бы «документ». Если переподготовка запускается кнопкой пуска / останова, вы можете использовать саму кнопку:

<a onclick="start(this);">Start</a>

<script>
function start(d){
    if (d.interval){
        clearInterval(d.interval);
        d.innerHTML='Start';
    } else {
        d.interval=setInterval(function(){
          //refresh here
        },10000);
        d.innerHTML='Stop';
    }
}
</script>

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


1
Что лучше о помещении его на documentчем window?
icktoofay

1
коррекция. Я хотел сказать document.body. В моем примере кода я эффективно использую саму кнопку. Для кнопки нет идентификатора, но указатель «this» связан с параметром «d» в функции. Использование «окна» в качестве области действия опасно, потому что там тоже есть функции. Например, «function test () {}» доступен через window.test, что аналогично тому, как вообще не используется область действия, потому что это сокращение. Надеюсь это поможет.
Schien

1
не теряйте переменные "scope-less" -> не используйте переменные "scope-less", я бы его отредактировал, но изменение меньше 6 букв, и ошибка сбивает с толку.
Лейф Неланд

2
Вам не нужно DOM для этого. Просто нам IIFE, чтобы избежать загрязнения глобального масштаба.
Онур Йылдырым

1
Я должен добавить 'd.interval = undefined' после innerhtml = 'start', чтобы он снова заработал. Потому что так работает только один раз.
Jocmtb

11

Уже ответил ... Но если вам нужен многофункциональный таймер многократного использования, который также поддерживает несколько задач с разными интервалами, вы можете использовать мой TaskTimer (для узла и браузера).

// Timer with 1000ms (1 second) base interval resolution.
const timer = new TaskTimer(1000);

// Add task(s) based on tick intervals.
timer.add({
    id: 'job1',         // unique id of the task
    tickInterval: 5,    // run every 5 ticks (5 x interval = 5000 ms)
    totalRuns: 10,      // run 10 times only. (omit for unlimited times)
    callback(task) {
        // code to be executed on each run
        console.log(task.name + ' task has run ' + task.currentRuns + ' times.');
        // stop the timer anytime you like
        if (someCondition()) timer.stop();
        // or simply remove this task if you have others
        if (someCondition()) timer.remove(task.id);
    }
});

// Start the timer
timer.start();

В вашем случае, когда пользователи нажимают за нарушение обновления данных; Вы также можете позвонить timer.pause()тогда, timer.resume()если они должны повторно включить.

Подробнее здесь .


6

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

setInterval всегда возвращает значение идентификатора. Это значение может быть передано в clearInterval (), чтобы остановить таймер. Вот пример таймера, который начинается с 30 и останавливается, когда он становится равным 0.

  let time = 30;
  const timeValue = setInterval((interval) => {
  time = this.time - 1;
  if (time <= 0) {
    clearInterval(timeValue);
  }
}, 1000);

5

@cnu,

Вы можете остановить интервал, когда попробуйте запустить код, прежде чем смотреть консольный браузер (F12) ... попробуйте комментарий clearInterval (триггер) - это снова выглядит консоль, а не beautifier? :П

Проверьте пример источника:

var trigger = setInterval(function() { 
  if (document.getElementById('sandroalvares') != null) {
    document.write('<div id="sandroalvares" style="background: yellow; width:200px;">SandroAlvares</div>');
    clearInterval(trigger);
    console.log('Success');
  } else {
    console.log('Trigger!!');
  }
}, 1000);
<div id="sandroalvares" style="background: gold; width:200px;">Author</div>


3

Объявите переменную, чтобы присвоить значение, возвращаемое из setInterval (...), и передать назначенную переменную в clearInterval ();

например

var timer, intervalInSec = 2;

timer = setInterval(func, intervalInSec*1000, 30 ); // third parameter is argument to called function 'func'

function func(param){
   console.log(param);
}

// Везде, где у вас есть доступ к таймеру, объявленному выше, вызов clearInterval

$('.htmlelement').click( function(){  // any event you want

       clearInterval(timer);// Stops or does the work
});

1
var keepGoing = true;
setInterval(function () {
     if (keepGoing) {
        //DO YOUR STUFF HERE            
        console.log(i);
     }
     //YOU CAN CHANGE 'keepGoing' HERE
  }, 500);

Вы также можете остановить интервал, добавив прослушиватель событий, скажем, для кнопки с идентификатором «stop-interval»:

$('buuton#stop-interval').click(function(){
   keepGoing = false;
});

HTML:

<button id="stop-interval">Stop Interval</button>

Примечание: интервал все равно будет выполнен, но ничего не произойдет.


2
Это действительно вернуло к производительности, и для фоновых вкладок, это на самом деле значительно замедлит все другие таймеры, так как таймеры и интервалы
задушены

1

Вот как я использовал метод clearInterval (), чтобы остановить таймер через 10 секунд.

function startCountDown() {
  var countdownNumberEl = document.getElementById('countdown-number');
  var countdown = 10;
  const interval = setInterval(() => {
    countdown = --countdown <= 0 ? 10 : countdown;
    countdownNumberEl.textContent = countdown;
    if (countdown == 1) {
      clearInterval(interval);
    }
  }, 1000)
}
<head>
  <body>
    <button id="countdown-number" onclick="startCountDown();">Show Time </button>
  </body>
</head>


1

Используйте setTimeOut, чтобы остановить интервал через некоторое время.

var interVal = setInterval(function(){console.log("Running")  }, 1000);
 setTimeout(function (argument) {
    clearInterval(interVal);
 },10000);

0

Я думаю, следующий код поможет:

var refreshIntervalId = setInterval(fname, 10000);

clearInterval(refreshIntervalId);

Вы сделали код на 100% правильным ... Итак ... В чем проблема? Или это учебник ...


-3

Почему бы не использовать более простой подход? Добавьте класс!

Просто добавьте класс, который говорит интервалу ничего не делать. Например: при наведении.

var i = 0;
this.setInterval(function() {
  if(!$('#counter').hasClass('pauseInterval')) { //only run if it hasn't got this class 'pauseInterval'
    console.log('Counting...');
    $('#counter').html(i++); //just for explaining and showing
  } else {
    console.log('Stopped counting');
  }
}, 500);

/* In this example, I'm adding a class on mouseover and remove it again on mouseleave. You can of course do pretty much whatever you like */
$('#counter').hover(function() { //mouse enter
    $(this).addClass('pauseInterval');
  },function() { //mouse leave
    $(this).removeClass('pauseInterval');
  }
);

/* Other example */
$('#pauseInterval').click(function() {
  $('#counter').toggleClass('pauseInterval');
});
body {
  background-color: #eee;
  font-family: Calibri, Arial, sans-serif;
}
#counter {
  width: 50%;
  background: #ddd;
  border: 2px solid #009afd;
  border-radius: 5px;
  padding: 5px;
  text-align: center;
  transition: .3s;
  margin: 0 auto;
}
#counter.pauseInterval {
  border-color: red;  
}
<!-- you'll need jQuery for this. If you really want a vanilla version, ask -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


<p id="counter">&nbsp;</p>
<button id="pauseInterval">Pause</button></p>

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


17
Мне не кажется, что это действительно проще ... Я также думаю, что чистее удалять интервалы, а не сохранять вызовы функций, которые ничего не делают.
Ромен Браун

Я не согласна this.setInterval(function() { if(!$('#counter').hasClass('pauseInterval')) { //do something } }, 500);это все, что у вас есть для кода. Более того, чек - это первое, что вы делаете, поэтому он очень легкий, когда его парят. Вот для чего это: временно приостановить функцию . Если вы хотите прекратить его на неопределенный срок: конечно, вы удалите интервал.
Аарт ден Брабер

Это равносильно опросу и, как правило, не рекомендуется. Он выведет процессор из состояния низкого энергопотребления только для выполнения (вероятной) бесполезной проверки. В этом примере также задерживается обратная связь от немедленной до 0-500 мс.
Чарли

Я полностью не согласен с вами, даже когда я написал код 2 года назад. В любом случае счетчик должен быть там, потому что ОП попросил его. Конечно, если вы используете это, например, для остановки счетчика после нажатия кнопки, это будет неоптимальным решением, но только для паузы при наведении курсора, это одно из самых простых доступных решений.
Аарт ден
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.