Ich habe mich gefragt, wie oft eine JavaScript- while
Anweisung (in der Chrome-Konsole) eine Variable in einer Millisekunde inkrementieren kann. Deshalb habe ich dieses Snippet schnell direkt in die Konsole geschrieben:
var run = true, i = 0;
setTimeout(function(){ run = false; }, 1);
while(run){ i++; }
Das Problem ist, dass es für immer läuft.
Warum passiert das und wie kann ich es lösen?
var run = true, i = 0; function loop() { i++; if (run) setTimeout(loop, 0); }; setTimeout(function() { run = false }, 1); loop();
Antworten:
Dies kommt auf die Ein-Thread-Natur von JavaScript 1 zurück . Was passiert ist so ziemlich das:
run = false
. Dies soll ausgeführt werden, nachdem die aktuelle Funktion ausgeführt wurde (oder was auch immer aktuell aktiv ist).setTimeout()
Rückruf ausgeführt undrun=false
.Wie Sie sehen können, wird ein
setTimeout()
Ansatz hier nicht funktionieren. Sie können dies umgehen, indem Sie die Zeit in derwhile
Bedingung überprüfen. Dies wird jedoch Ihre tatsächliche Messung beeinträchtigen.1 Zumindest für praktischere Zwecke können Sie es als Single-Threaded sehen. Eigentlich gibt es eine sogenannte "Ereignisschleife". In dieser Schleife werden alle Funktionen in die Warteschlange gestellt, bis sie ausgeführt werden. Wenn Sie eine neue Funktion in die Warteschlange stellen, wird sie an der entsprechenden Position in dieser Warteschlange abgelegt. Nachdem die aktuelle Funktion beendet wurde, nimmt die Engine die nächste Funktion aus der Warteschlange (in Bezug auf die eingeführten Timings, z. B. von
setTimeout()
und führt sie aus.Infolgedessen wird zu jedem Zeitpunkt nur eine Funktion ausgeführt, wodurch die Ausführung hübsch wird Es gibt einige Ausnahmen für Ereignisse, die im folgenden Link erläutert werden.
Als Referenz:
https://stackoverflow.com/a/16757582/1169798
Hier wurde ein ähnliches Szenario näher erläutert
https://stackoverflow.com/a/2734311/1169798
Eine ausführlichere Beschreibung, wann JS als Single-Threaded angesehen werden kann und wann nicht.
quelle
var start = (new Date()).getTime();
dann in derwhile
Anweisung diese Zeit von der aktuellen Zeit und prüfen Sie, ob die resultierende Zahl kleiner als die beabsichtigte Verzögerung ist .while ((new Date()).getTime() - start < delay)
.JavaScript ist Single-Threaded, sodass nichts anderes ausgeführt wird, während Sie sich in der Schleife befinden.
quelle
Um die wahre Geschwindigkeit von Chrome beizubehalten, ohne ständig die Zeit zur Berechnung der Geschwindigkeit abrufen zu müssen, können Sie diesen JS-Code ausprobieren:
var start = new Date().getTime() var i = 0 while(i<1000000) { i++ } var end = new Date().getTime() var delta = end-start var speed = i/delta console.log(speed + " loops per millisecond")
quelle
Javascript ist Single-Threaded, dh es wird jeweils nur eine Anweisung nacheinander ausgeführt.
Das Ereignissystem wird wie in vielen anderen Sprachen und Bibliotheken von einer Ereignisschleife verwaltet. Die Ereignisschleife ist im Grunde eine Schleife, die bei jeder Iteration nach Nachrichten in der Warteschlange sucht und Ereignisse auslöst.
In Javascript (wie in vielen Sprachen, die dieses Muster implementieren) wird die Ereignisschleife aufgerufen, wenn der Stapel leer ist, dh wenn alle Funktionen am Ende des Programmcodes zurückgegeben werden, dh.
Ihr "echtes" Programm sieht hinter den Kulissen ungefähr so aus:
var run = true, i = 0; setTimeout(function(){ run = false; }, 1); while(run){ i++; } while(true) { /* * check for new messages in the queue and dispatch * events if there are some */ processEvents(); }
Die Nachricht von der Uhr, dass das Zeitlimit abgelaufen ist, wird also nie verarbeitet.
Weitere Informationen zur Ereignisschleife finden Sie unter: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/EventLoop
Natürlich ist es etwas komplexer. Sehen Sie sich hier die folgenden Beispiele an: Ist JavaScript garantiert Single-Threaded? ( tl; dr: In einigen Browser-Engines sind einige externe Ereignisse nicht von der Ereignisschleife abhängig und werden sofort ausgelöst, wenn sie auftreten, wodurch die aktuelle Aufgabe verhindert wird. Dies ist jedoch bei setTimeout nicht der Fall, bei dem lediglich eine Nachricht zur Warteschlange hinzugefügt wird und feuert nie sofort.)
quelle
Die While-Schleife greift nicht auf das setTimeout zu. Sie haben Code, der setzt, dass true ausgeführt wird, und dann wird er niemals false.
quelle
JavaScript hat einen einzelnen Thread und überall einen einzelnen Thread.
Ich finde diese Frage gut: Ist JavaScript garantiert Single-Threaded?
Wenn sich Ihr Code in einer Schleife befindet, werden andere OCDE nicht ausgeführt und blockiert.
quelle