22 Stimmen

Kann eine setInterval-Funktion sich selbst anhalten?

Ich habe eine jsFiddle ein Beispiel, an dem wir arbeiten können.

$().ready(function() {
    $('.test').each(function() {
        $this = $(this);
        $this.data('Worker', function() {
            $('#stop').html((parseInt($('#stop').html()) + 1))
        })
        setInterval($this.data('Worker'), 100);
    });

    $('#stop').click(function() {
        // I want the worker function to stop being triggered here
        $('.test').remove();
    });
});

Ich möchte eine Worker-Funktion an ein Element im DOM anhängen, so dass, wenn das Element entfernt wird, die Worker-Funktion stoppt.

Ist so etwas möglich?

35voto

Ich bin spät dran, aber ich habe das so gelöst:

var id = setInterval(function()
{
    if(some_condition)
    {
        clearInterval(id);
    }
}, 1000);

Das ist definitiv der einfachste Weg von allen: keine unnötige Speicherung, keine Tricks.

17voto

Šime Vidas Punkte 172810

Hier ist es:

var stopBtn = $( '#stop' );

$( '.test' ).each(function ( i, elem ) {
    var tid = setInterval(function () {
        if ( elem.parentNode ) {
            stopBtn.html(function ( i, num ) { return parseInt(num,10) + 1; });
        } else {
            clearInterval( tid );
        }
    }, 1000);
});

stopBtn.click(function () {
    $( '.test' ).remove();
});

Erläuterung:

Zunächst einmal brauchen wir eine Schließung - die Intervallfunktion muss wissen, welches test-DIV ihr "Besitzer" ist, ergo müssen wir einen Verweis auf das DIV an die Intervallfunktion übergeben. In meinem Code wird dieser Verweis in der Datei elem die innerhalb der Intervallfunktion verfügbar ist, weil sie geschlossen ist. Die Intervallfunktion prüft also, ob ihr "Besitzer" DIV noch mit dem DOM verbunden ist (durch Untersuchung des übergeordneten Knotens) oder nicht. Ist dies der Fall, wird die Stopp-Schaltfläche inkrementiert. Ist dies nicht der Fall, wird das Intervall gelöscht. Um das Intervall jedoch löschen zu können, benötigen wir seine Timer-ID. Wir haben diese ID, weil wir sie in der Variable "tid" gespeichert haben (der setInterval-Aufruf gibt die Timer-ID zurück).

Live-Demo: http://jsfiddle.net/simevidas/ZjY7k/15/

3voto

Seize Punkte 59

Eine weitere Möglichkeit, Intervalle zu entfernen, ist die Verwendung von clearInterval innerhalb des Intervalls.

window.setInterval(function(){
    // Do all your stuff here
    if(/*something something*/){
        window.clearInterval(this);
        alert("The interval didn't clear");
    }
}, /*However long*/);

Wenn das Intervall nicht gelöscht wird, wird eine Warnung angezeigt: "Das Intervall wurde nicht gelöscht". Andernfalls wurde das Intervall erfolgreich gelöscht.

1voto

Steven Lu Punkte 38883

Ich vermute, dass die richtige Art und Weise, ein "selbstbeendendes" Intervall zu implementieren, darin besteht, das Intervall über eine Reihe von Timeouts zu implementieren.

In Semi-Pseudocode:

setTimeout(function repeat() {
  if (continue_to_run) // this code here may cause timing to be inaccurate
    setTimeout(repeat, interval_duration);
  do_task_on_interval();
}, 0)

Dieser Wiederholungstimer räumt hinter sich selbst auf.

1voto

Raúl Garcia Punkte 280

Vielleicht ist es zu spät, aber hier ist mein Beitrag:

/**
 * This function sleep each intervalMs until filter is true, when filter is true this function 
 * resolve promise and clean it self.
 * @param {*} intervalMs
 * @param {*} filter
 * @returns Promise<Void>
 */
const sleepUntil = (intervalMs, filter) => {
    let id = null;
    return new Promise((resolve) => {
        id = setInterval(() => {
            if (filter()) { resolve(); }
        }, intervalMs);
    }).then(() => {
        id = clearInterval(id);
    });
};

Ich verwende für Mutex Verhalten wie diese:

waitToSyncronize() {
    return sleepUntil(50, () => this.syncronizing === false);
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X