1119 Stimmen

Warum ist setTimeout(fn, 0) manchmal nützlich?

Ich bin kürzlich auf einen ziemlich fiesen Fehler gestoßen, bei dem der Code eine <select> dynamisch über JavaScript. Dieses dynamisch geladene <select> einen vorgewählten Wert hatte. Im IE6 hatten wir bereits Code, um den ausgewählten Wert zu fixieren <option> denn manchmal ist die <select> 's selectedIndex Wert nicht mit dem gewählten Wert übereinstimmen würde <option> 's index Attribut, wie unten dargestellt:

field.selectedIndex = element.index;

Dieser Code funktionierte jedoch nicht. Auch wenn das Feld selectedIndex richtig eingestellt war, wurde der falsche Index ausgewählt. Wenn ich jedoch einen alert() Anweisung zum richtigen Zeitpunkt die richtige Option ausgewählt werden würde. Da ich dachte, dass es sich um ein Zeitproblem handeln könnte, habe ich etwas Zufälliges ausprobiert, das ich bereits im Code gesehen hatte:

var wrapFn = (function() {
    var myField = field;
    var myElement = element;

    return function() {
        myField.selectedIndex = myElement.index;
    }
})();
setTimeout(wrapFn, 0);

Und es hat funktioniert!

Ich habe eine Lösung für mein Problem gefunden, aber ich weiß nicht genau, warum sie mein Problem behebt. Hat jemand eine offizielle Erklärung? Welches Browserproblem vermeide ich, indem ich meine Funktion "später" aufrufe, indem ich setTimeout() ?

2 Stimmen

Die meisten Fragen beschreiben, warum es nützlich ist. Wenn Sie wissen wollen, warum das so ist, lesen Sie meine Antwort: stackoverflow.com/a/23747597/1090562

35 Stimmen

Philip Roberts erklärt dies in seinem Vortrag "What the heck is the event loop?" auf die bestmögliche Weise. youtube.com/watch?v=8aGhZQkoFbQ

4 Stimmen

Wenn Sie es eilig haben, hier beginnt der Teil des Videos, in dem er genau auf die Frage eingeht: youtu.be/8aGhZQkoFbQ?t=14m54s . Trotzdem ist das ganze Video auf jeden Fall sehenswert.

8voto

user113716 Punkte 309387

Da es eine Dauer von 0 Ich nehme an, dass dies geschieht, um den Code zu entfernen, der an die setTimeout aus dem Fluss der Ausführung. Wenn es sich also um eine Funktion handelt, die eine Weile dauern könnte, wird sie die Ausführung des nachfolgenden Codes nicht verhindern.

0 Stimmen

FYI: Diese Antwort wurde hier zusammengeführt von stackoverflow.com/questions/4574940/

3voto

Jason Suárez Punkte 2305

Außerdem wird der Funktionsaufruf an das Ende des Stacks verschoben, um einen Stack-Überlauf zu verhindern, wenn Sie eine Funktion rekursiv aufrufen. Dies hat den Effekt einer while Schleife, sondern lässt die JavaScript-Engine andere asynchrone Timer auslösen.

0 Stimmen

Abwärtsstimme für dies push the function invocation to the bottom of the stack . Was stack über die Sie sprechen, ist unklar. Am wichtigsten ist, wo genau setTimeout fügt diese Funktion am Ende dieses Schleifenzyklus oder ganz am Anfang des nächsten Schleifenzyklus hinzu.

2voto

Jeremy Punkte 6410

Durch den Aufruf von setTimeout geben Sie der Seite Zeit, auf das zu reagieren, was der Benutzer gerade tut. Dies ist besonders hilfreich für Funktionen, die beim Laden der Seite ausgeführt werden.

2voto

Willem van der Veen Punkte 26043

Das Problem war, dass Sie versucht haben, eine Javascript-Operation auf einem nicht vorhandenen Element durchzuführen. Das Element wurde noch nicht geladen und setTimeout() gibt einem Element auf folgende Weise mehr Zeit zum Laden:

  1. setTimeout() bewirkt, dass das Ereignis ansynchron wird daher nach dem gesamten synchronen Code ausgeführt, wodurch Ihr Element mehr Zeit zum Laden erhält. Asynchrone Callbacks wie der Callback in setTimeout() werden in der Ereigniswarteschlange und auf den Stapel mit dem Ereignisschleife nachdem der Stapel mit synchronem Code leer ist.
  2. Der Wert 0 für ms als zweites Argument in der Funktion setTimeout() ist oft etwas höher (4-10 ms je nach Browser). Diese etwas längere Zeit, die für die Ausführung der setTimeout() Rückrufe wird durch die Anzahl der "Ticks" (wobei ein Tick bedeutet, dass ein Rückruf auf den Stapel geschoben wird, wenn der Stapel leer ist) der Ereignisschleife verursacht. Aus Gründen der Leistung und der Batterielebensdauer ist die Anzahl der Ticks in der Ereignisschleife auf eine bestimmte Anzahl beschränkt weniger als 1000 Mal pro Sekunde.

2voto

fabspro Punkte 1585

Einige andere Fälle, in denen setTimeout nützlich ist:

Sie möchten eine lang laufende Schleife oder Berechnung in kleinere Komponenten aufteilen, damit der Browser nicht "einfriert" oder sagt: "Skript auf der Seite ist beschäftigt".

Sie möchten eine Formularübermittlungsschaltfläche deaktivieren, wenn sie angeklickt wird, aber wenn Sie die Schaltfläche im onClick-Handler deaktivieren, wird das Formular nicht übermittelt. setTimeout mit einer Zeit von Null erfüllt den Zweck, so dass das Ereignis beendet wird, das Formular mit dem Übermitteln beginnt und die Schaltfläche dann deaktiviert werden kann.

2 Stimmen

Die Deaktivierung sollte besser im onsubmit-Ereignis erfolgen; sie wäre schneller und wird garantiert aufgerufen, bevor das Formular technisch übermittelt wird, da Sie die Übermittlung stoppen können.

0 Stimmen

Sehr richtig. Ich vermute, dass die Deaktivierung per Mausklick für die Prototypenerstellung einfacher ist, weil man einfach onclick="this.disabled=true" in die Schaltfläche eingeben kann, während die Deaktivierung beim Absenden etwas mehr Arbeit erfordert.

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