Arrêter l'appel setInterval en JavaScript

1399

J'utilise setInterval(fname, 10000);pour appeler une fonction toutes les 10 secondes en JavaScript. Est-il possible d'arrêter de l'appeler lors d'un événement?

Je veux que l'utilisateur puisse arrêter le rafraîchissement répété des données.

cnu
la source

Réponses:

2160

setInterval()renvoie un ID d'intervalle, que vous pouvez transmettre à clearInterval():

var refreshIntervalId = setInterval(fname, 10000);

/* later */
clearInterval(refreshIntervalId);

Voir les documents pour setInterval()et clearInterval().

John Millikin
la source
42
Comment pouvez-vous le redémarrer après l'arrêt avec 'clearInterval ()'? Si j'essaye de le redémarrer, je reçois 2x le setInterval en cours d'exécution.
Dan
8
Moi aussi à chaque fois que je veux utiliser SetInterval (MyFunction, 4000); ça devient de plus en plus rapide, à chaque fois 2 fois plus vite :( comment puis-je redémarrer un intervalle défini ??
Alireza Masali
14
SetInterval () ne change pas la vitesse à laquelle vous la passez. Si tout ce qu'il fait s'accélère à chaque fois que vous appelez SetInterval (), vous disposez de plusieurs minuteries qui s'exécutent en même temps et devraient ouvrir une nouvelle question.
EpicVoyage
29
Assurez-vous de vraiment l'arrêter. En raison de la portée des variables, il se peut que vous n'ayez pas le bon ID à appeler clearInterval. J'ai utilisé window.refreshIntervalIdau lieu d'une variable locale, et cela fonctionne très bien!
osa
2
J'ai commencé à attacher la poignée setInterval à son élément associé (le cas échéant): $('foo').data('interval', setInterval(fn, 100));puis à le supprimer avec clearInterval($('foo').data('interval'));Je suis sûr qu'il existe également un moyen non jQuery de le faire.
Michael - Où est Clay Shirky le
105

Si vous définissez la valeur de retour de setIntervalsur une variable, vous pouvez utiliser clearIntervalpour l'arrêter.

var myTimer = setInterval(...);
clearInterval(myTimer);
Quintin Robinson
la source
Je ne vois pas la différence entre cela et la réponse de John
Bobtroopo
51

Vous pouvez définir une nouvelle variable et la faire incrémenter de ++ (en compter une) à chaque exécution, puis j'utilise une instruction conditionnelle pour la terminer:

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

J'espère que cela aide et c'est juste.

OMGrant
la source
3
J'ai été surpris d'apprendre que cela fonctionne clearInterval(varName);. Je m'attendais clearIntervalà ne pas fonctionner une fois le nom de la fonction transmis, je pensais qu'il fallait l'ID d'intervalle. Je suppose que cela ne peut fonctionner que si vous avez une fonction nommée, car vous ne pouvez pas passer une fonction anonyme en tant que variable à l'intérieur de lui-même.
Patrick M
31
En fait, je pense que cela ne fonctionne pas. Le code cesse d'être exécuté en raison de la restriction sur le compteur, mais l'intervalle continue de déclencher varName (). Essayez de consigner quoi que ce soit après clearInterval () (à l'intérieur de la clause else) et vous verrez qu'il est écrit pour toujours.
Rafael Oliveira
5
Tant de votes positifs pour quelque chose qui ne fonctionne pas, parfois je ne comprends pas les gens sur SO: P
Stranded Kid
2
$(document).ready(function(){ });est jQuery, c'est pourquoi cela ne fonctionne pas. Cela aurait dû être mentionné au moins.
paddotk
4
@OMGrant, En plus d'un exemple qui ne fonctionne pas, vous avez une variable nommée varName, qui stocke une fonction sans nom - wha ?? Vous devriez changer ou retirer cette réponse, à mon humble avis.
Dean Radcliffe
13

Les réponses ci-dessus ont déjà expliqué comment setInterval renvoie un descripteur et comment ce descripteur est utilisé pour annuler le temporisateur d'intervalle.

Quelques considérations architecturales:

Veuillez ne pas utiliser de variables "sans portée". Le moyen le plus sûr consiste à utiliser l'attribut d'un objet DOM. L'endroit le plus simple serait le «document». Si le rafraîchissement est démarré par un bouton marche / arrêt, vous pouvez utiliser le bouton lui-même:

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

Puisque la fonction est définie à l'intérieur du gestionnaire de clic de bouton, vous n'avez pas besoin de la définir à nouveau. Le chronomètre peut être repris si le bouton est de nouveau cliqué.

Schien
la source
1
Quoi de mieux pour le mettre documentque pour le mettre window?
icktoofay
1
correction. Je voulais dire document.body. Dans mon exemple de code, j'utilise efficacement le bouton lui-même. Il n'y a pas d'ID pour le bouton, mais le pointeur "this" est lié au paramètre "d" dans la fonction. L'utilisation de "fenêtre" comme portée est risquée car les fonctions sont là aussi. Par exemple, "function test () {}" est accessible via window.test, ce qui revient à ne pas utiliser du tout de portée, car c'est un raccourci. J'espère que cela t'aides.
Schien
1
ne perdez pas les variables "sans portée" -> n'utilisez pas "sans portée" je l'aurais édité, mais le changement est inférieur à 6 lettres, et l'erreur prête à confusion.
Leif Neland
2
Vous n'avez pas besoin de DOM pour cela. Juste nous un IIFE pour éviter la pollution de portée mondiale.
Onur Yıldırım
1
Je dois ajouter 'd.interval = undefined' après innerhtml = 'start' pour le faire fonctionner à nouveau. Parce que ça marche juste une fois.
jocmtb
11

Déjà répondu ... Mais si vous avez besoin d'une minuterie en vedette, réutilisable qui prend également en charge plusieurs tâches à différents intervalles, vous pouvez utiliser mon TaskTimer (pour Node et navigateur).

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

Dans votre cas, lorsque les utilisateurs cliquent pour perturber l'actualisation des données; vous pouvez également appeler timer.pause()ensuite timer.resume()si elles ont besoin pour réactiver.

Voir plus ici .

Onur Yıldırım
la source
6

La méthode clearInterval () peut être utilisée pour effacer un ensemble de temporisations avec la méthode setInterval ().

setInterval renvoie toujours une valeur d'ID. Cette valeur peut être passée dans clearInterval () pour arrêter le temporisateur. Voici un exemple de temporisateur commençant à 30 et s'arrêtant quand il devient 0.

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

@cnu,

Vous pouvez arrêter l'intervalle, lorsque vous essayez d'exécuter du code avant de regarder votre navigateur de console (F12) ... : P

Vérifiez par exemple une source:

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
la source
3

Déclarez la variable pour affecter la valeur renvoyée par setInterval (...) et passez la variable affectée à clearInterval ();

par exemple

var timer, intervalInSec = 2;

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

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

// Partout où vous avez accès au minuteur déclaré ci-dessus, appelez clearInterval

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

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

Vous pouvez également arrêter l'intervalle en ajoutant un écouteur d'événements, disons un bouton avec l'ID "stop-interval":

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

HTML:

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

Remarque: L'intervalle sera toujours exécuté, mais rien ne se passera cependant.

Nadav
la source
2
C'est vraiment de retour pour les performances, et pour les onglets d'arrière-plan, cela ralentira considérablement tous les autres temporisateurs, car les temporisateurs et les intervalles sont
limités
1

C'est ainsi que j'ai utilisé la méthode clearInterval () pour arrêter le chronomètre après 10 secondes.

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
la source
1

Utilisez setTimeOut pour arrêter l'intervalle après un certain temps.

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

Je suppose que le code suivant vous aidera:

var refreshIntervalId = setInterval(fname, 10000);

clearInterval(refreshIntervalId);

Vous avez fait le code 100% correct ... Alors ... Quel est le problème? Ou c'est un tutoriel ...

Dangerousgame
la source
-3

Pourquoi ne pas utiliser une approche plus simple? Ajoutez une classe!

Ajoutez simplement une classe qui indique à l'intervalle de ne rien faire. Par exemple: en vol stationnaire.

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>

Je cherchais cette approche rapide et facile depuis des lustres, donc je poste plusieurs versions pour l'introduire autant de personnes que possible.

Aart den Braber
la source
17
Cela ne me semble pas vraiment plus simple ... Je pense aussi qu'il est plus propre de supprimer vos intervalles au lieu de garder les appels à des fonctions qui ne font rien.
Romain Braun
Je ne suis pas d'accord. this.setInterval(function() { if(!$('#counter').hasClass('pauseInterval')) { //do something } }, 500);est tout ce que vous avez pour le code. De plus, le chèque est la première chose que vous faites, il est donc très léger lorsqu'il est en vol stationnaire. C'est à cela que cela sert: suspendre temporairement une fonction . Si vous souhaitez y mettre fin indéfiniment: vous supprimez bien sûr l'intervalle.
Aart den Braber
Cela équivaut à un sondage et est généralement déconseillé. Il réveillera le processeur des états de faible puissance juste pour effectuer une vérification (probablement) inutile. Il retarde également le retour immédiat entre 0 et 500 ms dans cet exemple.
Charlie
Je ne suis pas du tout d'accord avec vous, même lorsque j'ai écrit le code il y a 2 ans. Le compteur doit être là de toute façon, car le PO l'a demandé. Bien sûr, si vous utilisez cela pour arrêter le compteur après avoir appuyé sur un bouton, par exemple, ce serait une solution sous-optimale, mais juste pour une pause en vol stationnaire, c'est l'une des solutions les plus simples disponibles.
Aart den Braber