Czy istnieje sposób na okresowe wywoływanie funkcji w JavaScript?

Odpowiedzi:

214

Chcesz setInterval():

var intervalID = setInterval(function(){alert("Interval reached");}, 5000);

Pierwszym parametrem do setInterval () może być również ciąg kodu do oceny.

Możesz wyczyścić funkcję okresową za pomocą:

clearInterval(intervalID);
zombat
źródło
15
Głosowałem za, a następnie zdecydowałem się wycofać mój głos za (ale nie przeciw), ponieważ używasz argumentu ciągu do setInterval. Funkcje powinny prawie zawsze być używane na rzecz argumentu typu string, ze względu na wydajność, bezpieczeństwo i ich właściwości zamykające.
Jason S
5
W porządku, nie mam nic przeciwko. setInterval()to poprawna odpowiedź na pytanie, bez względu na parametr. To tylko przykład, a obie metody są z definicji poprawne.
zombat
2
Zgadzam się z Jasonem S; to naprawdę powinna być funkcja. W twoim przykładzie jedynym problemem jest znikoma utrata wydajności, ale jest to zły nawyk.
Matthew Crumley,
4
Zgadzam się z wami obojgiem, używanie funkcji jest lepsze. Nigdy nie powiedziałem, że tak nie jest. Tak czy inaczej jest poprawna, ale ze względu na komentarze zmodyfikuję odpowiedź tak, aby zawierała funkcję.
zombat
37

Pamiętaj, że metoda setInterval () często nie jest najlepszym rozwiązaniem do okresowego wykonywania - to naprawdę zależy od tego, jaki javascript faktycznie wywołujesz okresowo.

na przykład. Jeśli używasz setInterval () z okresem 1000 ms iw funkcji okresowej wykonujesz wywołanie Ajax, które czasami zajmuje 2 sekundy, będziesz wykonywać kolejne wywołanie Ajax, zanim wróci pierwsza odpowiedź. Zwykle jest to niepożądane.

Wiele bibliotek ma okresowe metody, które chronią przed pułapkami wynikającymi z naiwnego używania setInterval, na przykład przykład Prototype podany przez Nelsona.

Aby uzyskać bardziej niezawodne wykonywanie okresowe z funkcją, która zawiera wywołanie jQuery ajax, rozważ coś takiego:

function myPeriodicMethod() {
  $.ajax({
    url: ..., 
    success: function(data) {
      ...
    },
    complete: function() {
      // schedule the next request *only* when the current one is complete:
      setTimeout(myPeriodicMethod, 1000);
    }
  });
}

// schedule the first invocation:
setTimeout(myPeriodicMethod, 1000);

Innym podejściem jest użycie setTimeout, ale śledzenie czasu, który upłynął w zmiennej, a następnie dynamiczne ustawianie opóźnienia limitu czasu przy każdym wywołaniu, aby wykonać funkcję tak blisko żądanego interwału, jak to możliwe, ale nigdy szybciej niż można uzyskać odpowiedzi.

Matt Coubrough
źródło
setTimeout (myPeriodicMethod, 1000); nazywa się 2 razy. czy jest to wymagane? Myślę, że wyznaczony czas powinien być wywoływany tylko w pełnej funkcji
Vishnudev K,
1
Tak, drugie setTimeout () nie jest wymagane, możesz po prostu wywołać myPeriodicMethod (), która natychmiast wykona pierwsze wywołanie ajax ... ale jeśli chcesz zaplanować to z opóźnieniem od pierwszego wywołania, możesz napisać to jako Napisałem.
Matt Coubrough
16

Każdy ma już rozwiązanie setTimeout / setInterval. Myślę, że ważne jest, aby pamiętać, że możesz przekazywać funkcje do setInterval, a nie tylko ciągi znaków. W rzeczywistości prawdopodobnie jest trochę „bezpieczniejsze” przekazywanie rzeczywistych funkcji zamiast ciągów, które będą „oceniane” do tych funkcji.

// example 1
function test() {
  alert('called');
}
var interval = setInterval(test, 10000);

Lub:

// example 2
var counter = 0;
var interval = setInterval(function() { alert("#"+counter++); }, 5000);
gnarf
źródło
3
+1 Jeśli jesteś uczniem Crockford school of JavaScript , unikasz eval we wszystkich jego złych formach.
Patrick McElhaney,
@Patrick - Nie sądzę, aby sugestia „Nie używaj znaku $ (znaku dolara) lub \ (ukośnika odwrotnego) w nazwach” będzie dobrze pasować do partii jQuery :)
Russ Cam
6

Stare pytanie, ale ... potrzebowałem też okresowego programu do uruchamiania zadań i napisałem TaskTimer . Jest to również przydatne, gdy musisz uruchomić wiele zadań w różnych odstępach czasu.

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

// Add task(s) based on tick intervals.
timer.addTask({
    name: 'job1',       // unique name of the task
    tickInterval: 5,    // run every 5 ticks (5 x interval = 5000 ms)
    totalRuns: 10,      // run 10 times only. (set to 0 for unlimited times)
    callback: function (task) {
        // code to be executed on each run
        console.log(task.name + ' task has run ' + task.currentRuns + ' times.');
    }
});

// Start the timer
timer.start();

TaskTimerdziała zarówno w przeglądarce, jak iw Node. Zobacz dokumentację dla wszystkich funkcji.

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

tak - przyjrzyj się setIntervalisetTimeout wykonaj kod w określonych momentach. setInterval będzie tym, który będzie używany do okresowego wykonywania kodu.

Zobacz demo i odpowiedz tutaj na użytkowanie

Russ Cam
źródło
2
function test() {
 alert('called!');
}
var id = setInterval('test();', 10000); //call test every 10 seconds.
function stop() { // call this to stop your interval.
   clearInterval(id);
}
Ben Lesh
źródło
1

Ponieważ chcesz, aby funkcja była wykonywana okresowo , użyj setInterval

CMS
źródło
1

Natywny sposób to rzeczywiście setInterval()/ clearInterval(), ale jeśli korzystasz już z biblioteki Prototype , możesz skorzystać z PeriodicalExecutor:

new PeriodicalUpdator(myEvent, seconds);

Zapobiega to nakładaniu się połączeń. Od http://www.prototypejs.org/api/periodicalExecuter :

„chroni Cię przed wieloma równoległymi wykonaniami funkcji zwrotnej, jeśli wykonanie tej funkcji potrwa dłużej niż określony interwał (utrzymuje wewnętrzną flagę„ uruchomiona ”, która jest chroniona przed wyjątkami w funkcji wywołania zwrotnego). Jest to szczególnie przydatne, jeśli użyj jednego do interakcji z użytkownikiem w określonych odstępach czasu (np. użyj zachęty lub potwierdź połączenie): pozwoli to uniknąć wielu okien wiadomości czekających na działanie. "

Nelson
źródło