Parar a chamada setInterval em JavaScript

1398

Estou usando setInterval(fname, 10000);para chamar uma função a cada 10 segundos em JavaScript. É possível parar de chamá-lo em algum evento?

Eu quero que o usuário possa parar a atualização repetida dos dados.

cnu
fonte

Respostas:

2160

setInterval()retorna um ID de intervalo, para o qual você pode passar clearInterval():

var refreshIntervalId = setInterval(fname, 10000);

/* later */
clearInterval(refreshIntervalId);

Veja os documentos para setInterval()e clearInterval().

John Millikin
fonte
42
Como você pode iniciá-lo novamente depois de parar com 'clearInterval ()'? Se eu tentar reiniciá-lo, recebo 2x o setInterval em execução.
Dan
8
Eu também Cada vez que eu quero usar SetInterval (MyFunction, 4000); -lo chegar mais rápido e mais rápido, cada vez 2x mais rápido tempo :( Como posso reiniciar um setInterval ??
Alireza Masali
14
SetInterval () não altera a velocidade que você passa. Se o que estiver fazendo acelerar cada vez que você chamar SetInterval (), você terá vários cronômetros em execução ao mesmo tempo e deverá abrir uma nova pergunta.
EpicVoyage
29
Verifique se você está realmente parando. Devido ao escopo da variável, talvez você não tenha o ID certo para chamar clearInterval. Eu usei em window.refreshIntervalIdvez de uma variável local e funciona muito bem!
osa 15/10
2
Comecei a anexar o identificador setInterval ao seu elemento associado (quando relevante): $('foo').data('interval', setInterval(fn, 100));e, em seguida, limpando-o com clearInterval($('foo').data('interval'));certeza de que também existe uma maneira não-jQuery.
Michael - Onde está Clay Shirky,
105

Se você definir o valor de retorno setIntervalpara uma variável, poderá usá clearInterval-lo para pará-lo.

var myTimer = setInterval(...);
clearInterval(myTimer);
Quintin Robinson
fonte
Não vejo a diferença entre isso e a resposta de John
Bobtroopo 03/04
51

Você pode definir uma nova variável e aumentá-la em ++ (conte até uma) toda vez que for executada, então eu uso uma instrução condicional para finalizá-la:

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

Espero que ajude e esteja certo.

OMGrant
fonte
3
Fiquei surpreso ao saber que isso funciona clearInterval(varName);. Eu esperava clearIntervalnão funcionar quando passou o nome da função, pensei que exigisse o ID do intervalo. Suponho que isso só funcione se você tiver uma função nomeada, pois não pode passar uma função anônima como uma variável dentro dela.
22712 Patrick M
31
Na verdade, acho que não funciona. O código para de ser executado devido à restrição no contador, mas o intervalo continua disparando varName (). Tente registrar qualquer coisa após clearInterval () (dentro da cláusula else) e você verá isso sendo gravado para sempre.
Rafael Oliveira
5
Tantas upvotes para algo que não funciona, às vezes eu não entendo as pessoas no SO: P
Stranded Kid
2
$(document).ready(function(){ });é jQuery, é por isso que não funciona. Isso deveria ter sido mencionado pelo menos.
paddotk
4
@OMGrant, além de um exemplo que não funciona, você tem uma variável chamada varName, que armazena uma função sem nome - wha ?? Você deve alterar ou derrubar esta resposta, IMHO.
Dean Radcliffe
13

As respostas acima já explicaram como setInterval retorna um identificador e como esse identificador é usado para cancelar o timer de intervalo.

Algumas considerações arquitetônicas:

Por favor, não use variáveis ​​"sem escopo". A maneira mais segura é usar o atributo de um objeto DOM. O lugar mais fácil seria "documento". Se a atualização for iniciada por um botão Iniciar / Parar, você poderá usar o próprio botão:

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

Como a função é definida dentro do manipulador de cliques do botão, você não precisa defini-la novamente. O temporizador pode ser retomado se o botão for clicado novamente.

Schien
fonte
1
O que há de melhor em colocá-lo do documentque em window?
icktoofay
1
correção. Eu quis dizer document.body. No meu exemplo de código, estou efetivamente usando o próprio botão. Não há ID para o botão, mas o ponteiro "this" está vinculado ao parâmetro "d" na função. Usar "janela" como escopo é arriscado, porque as funções também estão lá. Por exemplo, "function test () {}" pode ser acessado via window.test, que é o mesmo que não usar um escopo, porque é uma abreviação. Espero que isto ajude.
Schien
1
não perca variáveis ​​"sem escopo" -> não use "sem escopo" Eu a teria editado, mas a alteração é menor que 6 letras e o erro é confuso.
Leif Neland
2
Você não precisa de DOM para isso. Apenas um IIFE para evitar a poluição do escopo global.
Onur Yıldırım
1
Eu tenho que adicionar 'd.interval = undefined' após innerhtml = 'start' para fazê-lo funcionar novamente. Porque assim funciona apenas uma vez.
Jocmtb
11

Já respondi ... Mas se você precisar de um timer reutilizável em destaque que também suporte várias tarefas em diferentes intervalos, poderá usar meu TaskTimer (para Nó e navegador).

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

No seu caso, quando os usuários clicam para interromper a atualização de dados; você também pode chamar timer.pause(), em seguida, timer.resume()se eles precisam de re-ativar.

Veja mais aqui .

Onur Yıldırım
fonte
6

O método clearInterval () pode ser usado para limpar um conjunto de cronômetros com o método setInterval ().

setInterval sempre retorna um valor de ID. Este valor pode ser passado em clearInterval () para parar o cronômetro. Aqui está um exemplo de timer começando de 30 e para quando ele se torna 0.

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

@cnu,

Você pode parar o intervalo, quando tenta executar o código antes de procurar no navegador do console (F12) ... tente comentar clearInterval (trigger) é procurar novamente um console, não um embelezador? : P

Veja exemplo uma fonte:

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>

KingRider
fonte
3

Declare a variável para atribuir valor retornado de setInterval (...) e passe a variável atribuída para clearInterval ();

por exemplo

var timer, intervalInSec = 2;

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

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

// Em qualquer lugar que você tenha acesso ao timer declarado acima, chame clearInterval

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

       clearInterval(timer);// Stops or does the work
});
Yergalem
fonte
1
var keepGoing = true;
setInterval(function () {
     if (keepGoing) {
        //DO YOUR STUFF HERE            
        console.log(i);
     }
     //YOU CAN CHANGE 'keepGoing' HERE
  }, 500);

Você também pode interromper o intervalo adicionando um ouvinte de evento, digamos um botão com o ID "stop-interval":

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

HTML:

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

Nota: O intervalo ainda será executado, mas nada acontecerá.

Nadav
fonte
2
Este é realmente de volta para o desempenho e para guias de fundo, ele realmente vai abrandar todos os outros temporizadores por muito desde temporizadores e intervalos são estrangulados para guias fundo
Ferrybig
1

Foi assim que usei o método clearInterval () para parar o cronômetro após 10 segundos.

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>

Ishara Amarasekera
fonte
1

Use setTimeOut para interromper o intervalo após algum tempo.

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

Eu acho que o seguinte código ajudará:

var refreshIntervalId = setInterval(fname, 10000);

clearInterval(refreshIntervalId);

Você fez o código 100% correto ... Então ... Qual é o problema? Ou é um tutorial ...

Dangerousgame
fonte
-3

Por que não usar uma abordagem mais simples? Adicione uma turma!

Basta adicionar uma classe que diga ao intervalo para não fazer nada. Por exemplo: ao passar o mouse.

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>

Eu tenho procurado por essa abordagem rápida e fácil há muito tempo, por isso estou publicando várias versões para apresentar o maior número possível de pessoas.

Aart den Braber
fonte
17
Não me parece muito mais simples ... Também acho mais fácil remover seus intervalos em vez de manter chamadas para funções que não fazem nada.
Romain Braun
Eu não concordo this.setInterval(function() { if(!$('#counter').hasClass('pauseInterval')) { //do something } }, 500);é tudo que você tem para o código. Além disso, a verificação é a primeira coisa que você faz, por isso é muito leve quando está sendo pairada. É para isso que serve: pausar temporariamente uma função . Se você deseja finalizá-lo indefinidamente: é claro que você remove o intervalo.
Aart den Braber
Isso equivale a pesquisas e geralmente é desencorajado. Ele acordará a CPU a partir de estados de baixa energia apenas para fazer uma (provavelmente) verificação inútil. Também atrasa o feedback de imediato para entre 0 e 500 ms neste exemplo.
20917 Charlie
Não concordo totalmente com você, mesmo enquanto escrevi o código há 2 anos. O balcão deve estar lá de qualquer maneira, porque o OP pediu. Claro, se você estiver usando isso para parar o contador depois de pressionar um botão, por exemplo, essa seria uma solução abaixo do ideal, mas apenas para uma pausa ao passar o mouse, essa é uma das soluções mais simples disponíveis.
Aart den Braber