Zatrzymaj wywołanie setInterval w JavaScript

1398

Używam setInterval(fname, 10000);do wywoływania funkcji co 10 sekund w JavaScript. Czy można przestać nazywać go jakimś wydarzeniem?

Chcę, aby użytkownik mógł zatrzymać powtarzające się odświeżanie danych.

cnu
źródło

Odpowiedzi:

2160

setInterval()zwraca identyfikator interwału, który można przekazać clearInterval():

var refreshIntervalId = setInterval(fname, 10000);

/* later */
clearInterval(refreshIntervalId);

Zobacz dokumenty dla setInterval()i clearInterval().

John Millikin
źródło
42
Jak możesz uruchomić go ponownie po zatrzymaniu za pomocą „clearInterval ()”? Jeśli spróbuję go zrestartować, dostanę 2x działający setInterval.
Dan
8
Ja też Za każdym razem, gdy chcę użyć SetInterval (MyFunction, 4000); robi się coraz szybciej, za każdym razem 2x szybciej :( jak mogę zrestartować setinterval?
Alireza Masali
14
SetInterval () nie zmienia prędkości, którą przekazujesz. Jeśli cokolwiek robi, przyspiesza za każdym razem, gdy wywołujesz funkcję SetInterval (), oznacza to, że masz wiele timerów, które są uruchomione w tym samym czasie i powinieneś otworzyć nowe pytanie.
EpicVoyage
29
Upewnij się, że naprawdę to powstrzymujesz. Z powodu zmiennego zakresu, możesz nie mieć odpowiedniego identyfikatora, aby zadzwonić clearInterval. Użyłem window.refreshIntervalIdzamiast zmiennej lokalnej i działa świetnie!
osa
2
Zacząłem dołączać uchwyt setInterval do powiązanego elementu (jeśli dotyczy): $('foo').data('interval', setInterval(fn, 100));a następnie wyczyścić go za pomocą clearInterval($('foo').data('interval'));Jestem pewien, że istnieje również sposób inny niż jQuery.
Michael - Where's Clay Shirky
105

Jeśli ustawisz wartość zwracaną setIntervalzmiennej, możesz jej użyć, clearIntervalaby ją zatrzymać.

var myTimer = setInterval(...);
clearInterval(myTimer);
Quintin Robinson
źródło
Nie widzę różnicy między tym a odpowiedzią Johna
Bobtroopo
51

Możesz ustawić nową zmienną i zwiększać ją o ++ (policzyć jedną) za każdym razem, gdy się uruchomi, a następnie używam instrukcji warunkowej, aby ją zakończyć:

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

Mam nadzieję, że to pomaga i jest słuszne.

OMGrant
źródło
3
Byłem zaskoczony, gdy dowiedziałem się, że to działa clearInterval(varName);. Spodziewałem clearIntervalsię, że nie zadziała po przekazaniu nazwy funkcji, myślałem, że wymaga ID interwału. Przypuszczam, że to może działać tylko wtedy, gdy masz nazwaną funkcję, ponieważ nie możesz przekazać funkcji anonimowej jako zmiennej wewnątrz siebie.
Patrick M
31
Właściwie myślę, że to nie działa. Kod przestał być wykonywany z powodu ograniczenia licznika, ale interwał nadal uruchamia varName (). Spróbuj zalogować cokolwiek po clearInterval () (wewnątrz klauzuli else), a zobaczysz, że jest zapisywane na zawsze.
Rafael Oliveira,
5
Tyle głosów za czymś, co nie działa, czasami nie rozumiem ludzi na SO: P
Stranded Kid
2
$(document).ready(function(){ });jest jQuery, dlatego nie działa. Powinno to być przynajmniej wspomniane.
paddotk
4
@OMGrant, Oprócz przykładu, który nie działa, masz zmienną o nazwie varName, która przechowuje nienazwaną funkcję - co? Powinieneś zmienić lub usunąć tę odpowiedź, IMHO.
Dean Radcliffe
13

Powyższe odpowiedzi wyjaśniły już, w jaki sposób setInterval zwraca uchwyt i jak ten uchwyt służy do anulowania timera interwału.

Niektóre względy architektoniczne:

Nie używaj zmiennych „bez zakresu”. Najbezpieczniejszym sposobem jest użycie atrybutu obiektu DOM. Najłatwiejszym miejscem byłoby „dokument”. Jeśli odświeżanie jest uruchamiane przyciskiem Start / Stop, możesz użyć samego przycisku:

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

Ponieważ funkcja jest zdefiniowana w module obsługi kliknięcia przycisku, nie trzeba jej ponownie definiować. Timer można wznowić po ponownym kliknięciu przycisku.

Schien
źródło
1
Co jest lepszego w zakładaniu documentniż na window?
icktoofay
1
korekta. Chciałem powiedzieć document.body. W moim przykładzie kodu skutecznie używam samego przycisku. Przycisk nie ma identyfikatora, ale wskaźnik „ten” jest powiązany z parametrem „d” w funkcji. Używanie „okna” jako zakresu jest ryzykowne, ponieważ funkcje też tam są. Na przykład „test funkcji () {}” jest dostępny poprzez window.test, co oznacza to, że w ogóle nie używa się zakresu, ponieważ jest to skrót. Mam nadzieję że to pomoże.
Schien
1
nie trać zmiennych „bez zakresu” -> nie używaj „bez zakresu” Zredagowałbym to, ale zmiana jest mniejsza niż 6 liter, a błąd jest mylący.
Leif Neland,
2
Nie potrzebujesz do tego DOM. Tylko nam IIFE, aby uniknąć globalnego zanieczyszczenia zakresu.
Onur Yıldırım
1
Muszę dodać „d.interval = undefined” po innerhtml = „start”, aby znów działało. Ponieważ tak to działa tylko raz.
jocmtb
11

Już odpowiedziałem ... Ale jeśli potrzebujesz funkcjonalnego, wielokrotnego użytku timera, który obsługuje również wiele zadań w różnych odstępach czasu, możesz użyć mojego TaskTimer (dla Węzła i przeglądarki).

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

W twoim przypadku, gdy użytkownicy klikną, aby zakłócić odświeżanie danych; Można również zadzwonić timer.pause()wtedy timer.resume(), jeśli trzeba ponownie włączyć.

Zobacz więcej tutaj .

Onur Yıldırım
źródło
6

Za pomocą metody clearInterval () można wyczyścić zestaw liczników czasu za pomocą metody setInterval ().

setInterval zawsze zwraca wartość identyfikatora. Tę wartość można przekazać w funkcji clearInterval (), aby zatrzymać stoper. Oto przykład licznika czasu rozpoczynającego się od 30 i zatrzymującego się, gdy staje się 0.

  let time = 30;
  const timeValue = setInterval((interval) => {
  time = this.time - 1;
  if (time <= 0) {
    clearInterval(timeValue);
  }
}, 1000);
Sksaif Uddin
źródło
5

@cnu,

Możesz zatrzymać interwał, kiedy spróbujesz uruchomić kod, zanim przejrzysz przeglądarkę konsoli (F12) ... spróbuj skomentować clearInterval (wyzwalacz) to znów konsola, a nie upiększacz? : P

Sprawdź przykład źródło:

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
źródło
3

Zadeklaruj zmienną, aby przypisać wartość zwróconą z setInterval (...) i przekaż przypisaną zmienną do clearInterval ();

na przykład

var timer, intervalInSec = 2;

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

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

// Gdziekolwiek masz dostęp do timera zadeklarowanego powyżej, zadzwoń clearInterval

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

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

Możesz także zatrzymać interwał, dodając detektor zdarzeń, aby powiedzieć, że mamy przycisk o identyfikatorze „stop-interwał”:

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

HTML:

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

Uwaga: interwał będzie nadal wykonywany, ale nic się nie wydarzy.

Nadav
źródło
2
To naprawdę wróciło do wydajności, a dla kart w tle znacznie spowolni wszystkie inne liczniki, ponieważ liczniki i interwały są dławione dla kart w tle
Ferrybig
1

W ten sposób użyłem metody clearInterval (), aby zatrzymać stoper po 10 sekundach.

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
źródło
1

Użyj setTimeOut, aby zatrzymać interwał po pewnym czasie.

var interVal = setInterval(function(){console.log("Running")  }, 1000);
 setTimeout(function (argument) {
    clearInterval(interVal);
 },10000);
Syed Shibli
źródło
0

Myślę, że następujący kod pomoże:

var refreshIntervalId = setInterval(fname, 10000);

clearInterval(refreshIntervalId);

Czy kod był w 100% poprawny ... Więc ... W czym problem? Lub to samouczek ...

Niebezpieczna gra
źródło
-3

Dlaczego nie zastosować prostszego podejścia? Dodaj klasę!

Po prostu dodaj klasę, która mówi interwałowi, żeby nic nie robił. Na przykład: po najechaniu myszą.

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>

Od lat szukałem tego szybkiego i łatwego podejścia, dlatego publikuję kilka wersji, aby przedstawić jak najwięcej osób.

Aart den Braber
źródło
17
Nie wydaje mi się to naprawdę prostsze ... Myślę też, że łatwiej jest usuwać interwały zamiast utrzymywać wywołania funkcji, które nic nie robią.
Romain Braun
Nie zgadzam się this.setInterval(function() { if(!$('#counter').hasClass('pauseInterval')) { //do something } }, 500);to wszystko, co masz do kodu. Co więcej, czek jest pierwszą rzeczą, którą robisz, więc jest bardzo lekki, gdy się go unosi. Do tego właśnie służy: tymczasowe wstrzymanie funkcji . Jeśli chcesz go zakończyć na czas nieokreślony: oczywiście usuwasz odstęp.
Aart den Braber
Sprowadza się to do głosowania i ogólnie jest odradzane. Budzi procesor ze stanów niskiego poboru mocy, aby wykonać (prawdopodobnie) bezużyteczne sprawdzenie. W tym przykładzie opóźnia również sprzężenie zwrotne od natychmiastowego do od 0 do 500 ms.
Charlie,
Całkowicie się z tobą nie zgadzam, nawet gdy napisałem kod 2 lata temu. I tak licznik musi tam być, ponieważ OP poprosił o to. Jasne, jeśli używasz tego do zatrzymania licznika po naciśnięciu przycisku, byłoby to na przykład nieoptymalne rozwiązanie, ale tylko dla pauzy podczas najechania kursorem, jest to jedno z najprostszych dostępnych rozwiązań.
Aart den Braber