Heim >Web-Frontend >js-Tutorial >Vertieftes Verständnis des JavaScript-Ausführungsmechanismus
Der Inhalt dieses Artikels befasst sich mit einem umfassenden Verständnis des JavaScript-Ausführungsmechanismus. Er hat einen gewissen Referenzwert. Ich hoffe, dass er für Sie hilfreich ist.
Zuallererst wissen wir alle, dass JavaScript eine Single-Threaded-Sprache ist, daher können wir schlussfolgern:
JavaScript wird in der Reihenfolge der Anweisungen ausgeführtErster Blick:
let a = '1' console.log(a) let b = '2' console.log(b)
Natürlich kennt jeder das Ergebnis, das 1, 2 nacheinander ausgibt
Allerdings auch anders:
setTimeout(function() { console.log(1) }) new Promise(function(resolve) { console.log(2) for(var i = 0;i< 10;i++){ i === 10 && resolve() } }).then(function() { console.log(3) }) console.log(4)
Sehen Sie sich zu diesem Zeitpunkt die sequentielle Ausführung des Codes an, Ausgabe 1, 2, 3, 4. Okay, lege es in den Browser und führe es aus, was? Die Ausgabe ist tatsächlich 2, 4, 3, 1. Wie wäre es, sie in der versprochenen Reihenfolge auszuführen? Als nächstes müssen wir den Ausführungsmechanismus von JavaScript verstehen.
Zuallererst ist JavaScript eine Single-Thread-Sprache. Beim neuesten HTML5-Start von Web-Worker hat sich der Kern, dass JavaScript eine Single-Thread-Sprache ist, nicht geändert . Daher wird JavaScript-Multithreading basierend auf einem einzelnen Thread simuliert. Bedenken Sie also, dass JavaScript eine Single-Threaded-Sprache ist.
Aufgaben sind in zwei Kategorien unterteilt:
Synchrone Aufgaben
Asynchrone Aufgaben
Wenn wir die Seite öffnen, ist das Rendern der Seite eine Menge synchroner Aufgaben, und die zeitaufwändigen Aufgaben wie das Laden von Bildern und Audioressourcen sind asynchrone Aufgaben. Der Hauptinhalt der Zeitschleife ist:
Wenn eine Aufgabe in den Ausführungsstapel gelangt, bestimmen Sie, ob es sich um eine synchrone Aufgabe oder eine asynchrone Aufgabe handelt Führen Sie den Hauptthread aus und geben Sie die Funktion „Ereignistabelle asynchron“ ein.
Wenn das angegebene Ereignis abgeschlossen ist, verschiebt die Ereignistabelle diese Funktion in die Ereigniswarteschlange
Nachdem die Aufgabe im Hauptthread abgeschlossen ist , go Die Aufgabenwarteschlange liest die entsprechende Funktion und tritt in den Hauptthread ein, um sie auszuführen
Der obige Vorgang wird kontinuierlich wiederholt, was eine Ereignisschleife bildet
unter denen js Die Engine verfügt über einen Überwachungsprozess, der ständig prüft, ob der Haupt-Thread-Ausführungsstapel leer ist. Sobald er leer ist, geht er in die Zeitwarteschlange, um zu prüfen, ob Funktionen auf den Aufruf warten.
Zum Beispiel:
setTimeout( function() { console.log(1) }, 0) console.log(2)
Zuerst setTimeout und die Ereignistabelle eingeben
Konsole.log(2) ausführen
Die von setTimeout ausgeführte Funktion gelangt in die Ereigniswarteschlange
Der Hauptthread liest die Funktionsausführung aus der Ereigniswarteschlange
Aus diesem Grund wird die Funktion nicht sofort ausgeführt, selbst wenn setTimeout(fn, 0)
gesetzt ist. Selbst wenn der Hauptthread leer ist, können 0 ms nicht erreicht werden. Gemäß dem HTML-Standard beträgt das Minimum 4 ms.
hat auch eine ähnliche Funktion wie setTimeout
, die für setInterval
in einer Schleife ausgeführt wird. Bezüglich der Ausführungsreihenfolge platziert setInterval
die registrierte Funktion in bestimmten Abständen in der Ereigniswarteschlange. Wenn die vorherige Aufgabe zu lange dauert, müssen Sie ebenfalls warten.
Beachten Sie jedoch, dass setInterval(fn, ms)
nicht jedes Mal ausgeführt wird, wenn ms
ausgeführt wird, sondern jedes Mal, wenn ms
ausgeführt wird, fn
in die Aufgabenwarteschlange aufgenommen wird. Das heißt, wenn das Ausführungsereignis der Rückruffunktion von setInterval
die Verzögerung ms
überschreitet, ist das Ereignisintervall nicht sichtbar.
Neben verallgemeinerten synchronen Aufgaben und asynchronen Aufgaben gibt es auch detailliertere Aufteilungen von Aufgaben, die unterteilt sind in:
Makroaufgabe (Makroaufgabe): einschließlich des gesamten Codeskripts, setTimeout, setInterval
Mikroaufgabe (Mikroaufgabe): Promise, process.nextTick
Die Reihenfolge der Ereignisschleife bestimmt die Ausführungsreihenfolge des JS-Codes. Nach Eingabe des Gesamtcodes (Makrotask) startet der erste Zyklus. Führen Sie dann alle Mikrotasks aus. Beginnen Sie dann erneut mit der Makroaufgabe, suchen Sie eine der auszuführenden Aufgabenwarteschlangen und führen Sie dann alle Mikroaufgaben aus.
Verwenden Sie einen Code zur Veranschaulichung:
setTimeout(function() { console.log('1'); }) new Promise(function(resolve) { console.log('2'); resolve() }).then(function() { console.log('3'); }) console.log('4');
Dieser Code wird als Makroaufgabe verwendet, um den ersten Zyklus zu starten
Zuerst, wenn setTimeout
angetroffen wird, dann tritt seine Rückruffunktion in die Ereigniswarteschlange der Makroaufgabe ein
Wenn Promise
angetroffen wird, wird Promise
sofort ausgeführt, gibt 2 aus und Die then
Aufgabe wird eingegeben. Gehen Sie zur Mikrotask-Ereigniswarteschlange.
Die Konsole wird unten angetroffen und gibt 4 aus.
Die erste Makroaufgabe endet , schauen Sie sich die Mikrotask-Ereigniswarteschlange an, Ausführen then
, Ausgabe 3
Die erste Runde der Schleife endet, sehen Sie sich die Ausführung der Rückruffunktion setTimeout in der Makrotask-Warteschlange an, Ausgabe 1
Alle Ergebnisse sind: 2, 4, 3, 1
Nachdem wir die Grundprinzipien verstanden haben, schauen wir uns ein komplizierteres an:
console.log('1'); setTimeout(function() { console.log('2'); process.nextTick(function() { console.log('3'); }) new Promise(function(resolve) { console.log('4'); resolve(); }).then(function() { console.log('5') }) }) process.nextTick(function() { console.log('6'); }) new Promise(function(resolve) { console.log('7'); resolve(); }).then(function() { console.log('8') }) setTimeout(function() { console.log('9'); process.nextTick(function() { console.log('10'); }) new Promise(function(resolve) { console.log('11'); resolve(); }).then(function() { console.log('12') }) })
Weiß nicht. Was ist deine Antwort? Als nächstes analysieren wir es:
Erste Runde:
Zuerst geht der gesamte Code als Makroaufgabe in den Hauptthread ein und trifft zunächst auf console.log()
Ausgabe 1
Begegnen Sie dem ersten setTimeout()
und betreten Sie die Makroaufgabenwarteschlange
Betreten Sie den ersten Process.nextTick()
und betreten Sie die Mikroaufgabenwarteschlange
trifft dann auf Promise
, wird sofort ausgeführt, gibt 7 aus und then
wird zur Mikrotask-Warteschlange hinzugefügt
trifft auf das zweite setTimeout
, Geben Sie die Makroaufgabenwarteschlange ein
und führen Sie dann zwei Mikroaufgaben aus
ausführen Process.nextTick()
Ausgabe 6
Ausführenthen
, Ausgabe 8
Auf diese Weise ist die erste Runde der Schleife vollständig beendet und die zweite Runde der Ereignisschleife wird ausgeführt, also die erste setTimeout
erste Begegnungen console.log()
, gibt 2
Begegnungen Process.nextTick()
aus, tritt in die Mikrotask-Warteschlange ein
Wenn Sie auf Promise
stoßen, führen Sie sofort Ausgabe 4 aus, then
geben Sie die Mikrotask-Warteschlange ein
und führen Sie dann die erste Mikrotask aus, Ausgabe 3
Dann ausführen, 5 ausgeben
Auf diese Weise ist die zweite Runde der Ereignisschleife beendet und schließlich wird das zweite setTimeout
und das zweite ähnelt dem oben genannten Prinzip, daher werde ich die Erklärung nicht wiederholen. Das Endergebnis ist also: setTimeout
1,7,6,8,2,4,3,5,9,11,10,12
Detaillierte Erläuterung von Beispielen für js-Ausführungsmechanismen
JavaScript Laufmechanismus Ereignisschleife
Das obige ist der detaillierte Inhalt vonVertieftes Verständnis des JavaScript-Ausführungsmechanismus. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!