2009-06-15 19 views
12

Mein Problem ist, dass ich einen Timer nicht stoppen kann.Stop Settimeout in rekursive Funktion

Ich hatte this method, um eine Zeitüberschreitung aus diesem Forum zu setzen. Es sollte den Identifikator in der globalen Variable speichern. Durch Zufall habe ich herausgefunden, dass es immer noch läuft, nachdem ich "mydiv" versteckt habe.

Ich muss jetzt auch wissen, ob die rekursive Funktion mehrere Instanzen oder nur eine für die Timeouts erstellt. Weil ich zuerst dachte, dass es "var mytimer" jedes Mal überschreibt. Jetzt bin ich mir nicht so sicher.

Was wäre ein solider Weg, um den Timer zu stoppen?

var updatetimer= function() { 
//do stuff 
     setTimeout(function(){updatetimer();}, 10000); 

}//end function 


//this should start and stop the timer 
$("#mybutton").click(function(e) { 
     e.preventDefault(); 
     if($('#mydiv').is(':visible')){ 
        $('#mydiv').fadeOut('normal'); 
      clearTimeout(updatetimer); 

     }else{ 
        $('#mydiv').fadeIn('normal'); 
        updatetimer(); 
       } 
}); 

Dank, Richard

Antwort

7

Ich glaube, Sie mißverstehen 'SetTimeout' und 'clear'.

Wenn Sie einen Timer einstellen möchten, die Sie später abbrechen möchten, so etwas wie:

foo = setTimeout(function, time); 

dann

clearTimeout(foo); 

nennen, wenn Sie diesen Timer abbrechen möchten.

Hoffe, das hilft!

+0

ich würde sagen, es ist ziemlich schlecht - es ist funktional, aber Es gibt keine Möglichkeit, sie abzubrechen (weil der Wert von setTimeout nicht erfasst wird), aber das ist leicht zu beheben und trivial im Vergleich zu einer Anfrage pro Sekunde. Das ist wirklich übertrieben, imho. – annakata

+0

danke, jetzt verstehe ich meinen eigenen Code nicht mehr. Was ist der Vorteil off diese anonymen Funktionen sowieso verwenden? Sehen Sie den Link –

+0

das ist eine ganz andere Frage, weil die Antwort ziemlich weit reichend ist :) – annakata

2

Wie geschrieben, Mytimer ist eine Funktion, die nie den Wert eines Timeout-Bezeichners hat, daher wird Ihre ClearTimeout-Anweisung nichts erreichen.

Ich sehe keine Rekursion hier überhaupt, aber Sie müssen den Wert SetTimeout kehren Sie speichern, und wenn Sie dies mit mehreren potenziellen Ereignisse paaren müssen, müssen Sie es gegen einen Schlüsselwert zu speichern, können Sie Nachschlagen - so etwas wie eine Element-ID vielleicht?

+0

Ich verstehe, was Sie sagen. –

0

Wie oben erwähnt, ist der Hauptgrund, warum dieser Code nicht funktioniert, ist, dass Sie passingt er falsche Sache in die clearTimeout Gespräch führen - Sie den Rückgabewert speichern, müssen von der setTimeout Sie in updateFunction machen anrufen und passieren Diese in ClearTimeout, anstelle der Funktion Referenz selbst.

Als zweiten Verbesserungsvorschlag - wann immer Sie eine rekursive Timeout-Funktion haben, sollten Sie besser die Methode setInterval verwenden, die eine Funktion in regelmäßigen Abständen bis zum Abbruch ausführt. Dies wird das gleiche erreichen, was Sie mit Ihrer Methode updateFunction erreichen wollen, aber es ist sauberer, da Sie nur die "Do-stuff" -Logik in die Deferred-Funktion einbeziehen müssen, und es ist wahrscheinlich performanter, da Sie nicht verschachtelt werden Verschlüsse. Plus es ist der richtige Weg, es zu tun, was für etwas zählen muss, oder? :-)

+0

Aus der Diskussion unter http://stackoverflow.com/questions/729921/settimeout-or-terinterval ist setInterval nicht immer besser. – billyswong

+0

ja, von dieser Diskussion allein, bekommen Sie die Vorstellung, dass es tendenziell Timeout als die bevorzugte Methode verwendet. weil setinterval quees zum Beispiel auf. Ich weiß nichts über verschachtelte Verschlüsse. Vielleicht hast du recht damit. –

20

Ich denke, dass die meisten Leute den Grund bekommen, warum das nicht funktioniert, aber ich dachte, ich würde Ihnen mit aktualisierten Code zur Verfügung stellen. Es ist ungefähr dasselbe wie Ihres, außer dass es das Timeout einer Variablen zuweist, damit es gelöscht werden kann.

Auch die anonyme Funktion in einem setTimeout ist groß, , wenn Sie inline-Logik ausführen möchten, ändern Sie den Wert von "this" innerhalb der Funktion oder übergeben Sie Parameter in eine Funktion.Wenn Sie nur eine Funktion aufrufen möchten, genügt es, den Namen der Funktion als ersten Parameter zu übergeben.

var timer = null; 

var updatetimer = function() { 
    //do stuff 

    // By the way, can just pass in the function name instead of an anonymous 
    // function unless if you want to pass parameters or change the value of 'this' 
    timer = setTimeout(updatetimer, 10000); 
}; 

//this should start and stop the timer 
$("#mybutton").click(function(e) { 
    e.preventDefault(); 
    if($('#mydiv').is(':visible')){ 
     $('#mydiv').fadeOut('normal'); 
     clearTimeout(timer); // Since the timeout is assigned to a variable, we can successfully clear it now 

    } else{ 
     $('#mydiv').fadeIn('normal'); 
     updatetimer(); 
    } 
}); 
0

(function() {

$('#my_div').css('background-color', 'red'); 
$('#my_div').hover(function(){ 
var id=setTimeout(function() { 
    $('#my_div').css('background-color', 'green'); 
}, 2000); 

var id=setTimeout(function() { 
    $('#my_div').css('background-color', 'blue'); 
}, 4000); 
var id=setTimeout(function() { 
    $('#my_div').css('background-color', 'pink'); 
}, 6000); 

    }) 

$("#my_div").click(function(){ 
     clearTimeout(id); 

     }) 

})();

+1

Können Sie [bearbeiten] und erklären, wie dies die Frage beantwortet? – yhw42

0

Sie können nicht alle Funktionen stoppen, die erstellt werden, intead davon wandeln die Funktion setInterval (repräsentieren die gleiche Logik, die Ihre rekursive Funktion) und beenden es:

// recursive 
var timer= function() { 
// do stuff 
    setTimeout(function(){timer();}, 10000); 
} 

Die gleiche Logik setInterval mit:

// same logic executing stuff in 10 seconds loop 
var timer = setInterval(function(){// do stuff}, 10000) 

Stop it:

clearInterval(timer);