Heim  >  Artikel  >  Web-Frontend  >  JS-Betriebsmechanismus: Analyse der Synchronisation, Asynchronität und Ereignisschleife (Ereignisschleife)

JS-Betriebsmechanismus: Analyse der Synchronisation, Asynchronität und Ereignisschleife (Ereignisschleife)

不言
不言Original
2018-08-07 15:41:281504Durchsuche

Was dieser Artikel Ihnen bringt, ist die Analyse des JS-Betriebsmechanismus: Synchronisation, Asynchronität und Ereignisschleife (Ereignisschleife). Ich hoffe, dass er Ihnen helfen wird Du hast geholfen.

1. Warum JS Single-Threaded ist

Ein Hauptmerkmal der Javascript-Sprache ist, dass sie Single-Threaded ist und nur das Gleiche gleichzeitig tun kann. Warum kann JS also nicht Multi-Threaded sein?

Als Browser-Skriptsprache besteht der Hauptzweck von Javascript darin, mit Benutzern zu interagieren und das DOM zu bedienen. Dies legt fest, dass es nur Single-Threaded sein kann, da es sonst sehr komplex wird Synchronisationsprobleme. Beispiel: Angenommen, Javascript verfügt über zwei Threads gleichzeitig. Ein Thread fügt Inhalt zu einem bestimmten DOM-Knoten hinzu und der andere Thread löscht einen Knoten. Welchen sollte der Browser in diesem Fall verwenden?

Um Komplexität zu vermeiden, ist Javascript seit seiner Geburt Single-Threaded. Dies ist zum Kernmerkmal dieser Sprache geworden und wird sich auch in Zukunft nicht ändern.

Um die Rechenleistung von Multi-Core-CPUs zu nutzen, schlägt HTML5 den Web-Woker-Standard vor, der es Javascript-Skripten ermöglicht, mehrere Threads zu erstellen, die untergeordneten Threads jedoch vollständig kontrolliert werden vom Hauptthread und kann das DOM nicht bedienen. Daher ändert dieser neue Standard nichts an der Single-Threaded-Natur von JavaScript.

2. Synchron und asynchron

Angenommen, es gibt eine Funktion A:

A(args...){...}

Synchronisation: Wenn der Aufrufer beim Aufruf von Funktion A sofort das erwartete Ergebnis erhalten kann, dann ist diese Funktion synchron.

Asynchron: Wenn der Aufrufer beim Aufruf von Funktion A das erwartete Ergebnis nicht sofort erhalten kann, sondern es in Zukunft auf bestimmte Weise (zeitaufwendig, Verzögerung, Ereignisauslösung) erhalten muss, ist diese Funktion asynchron .

3. Wie JS asynchrone Vorgänge implementiert

Obwohl JS Single-Threaded ist, ist der Browser-Kernel Multi-Threaded Es werden zusätzliche Threads für einige zeitaufwändige Aufgaben erstellt und von verschiedenen Browser-Kernelmodulen ausgeführt. Beispielsweise werden onlcik, setTimeout und ajax vom DOM im Browser-Kernel auf unterschiedliche Weise verarbeitet. Bingding-, Netzwerk- und Timer-Module werden ausgeführt. Wenn die ausgeführte Aufgabe das laufende Ergebnis erhält, wird die entsprechende Rückruffunktion in die Aufgabenwarteschlange gestellt. Daher war JS schon immer Single-Threaded und es ist der Browser, der asynchrone Vorgänge implementiert.

Wenn im obigen Bild DOM-Anfragen, Ajax-Anfragen, setTimeout und andere WebAPIs im Aufrufstapel angetroffen werden, werden diese an andere Module des Browserkernels übergeben zur Verarbeitung, Webkit Zusätzlich zur Javascript-Ausführungs-Engine verfügt der Kernel über ein wichtiges Modul namens Webcoew-Modul. Für die drei in der Abbildung von WebAPIs genannten APIs stellt Webcore jeweils DOM-Bindungs-, Netzwerk- und Timer-Module bereit, um die zugrunde liegende Implementierung zu verwalten. Wenn diese Module die Verarbeitung dieser Vorgänge abgeschlossen haben, stellen Sie die Rückruffunktion in die Aufgabenwarteschlange und warten Sie dann, bis die Aufgaben im Stapel ausgeführt werden, bevor Sie die Rückruffunktion in der Aufgabenwarteschlange ausführen.

Zusammenfassung:

1. Alle Codes müssen durch Aufrufe im Funktionsaufrufstapel ausgeführt werden

2. Wenn die oben genannten APIs auftreten, werden sie zur Verarbeitung an andere Module des Browserkernels übergeben

3 Die Rückruffunktion wird in der Aufgabenwarteschlange gespeichert

4. Warten Sie, bis die Aufgabe im Aufrufstapel ausgeführt wird, und kehren Sie dann zurück, um die Aufgabe in der Aufgabenwarteschlange auszuführen

Der Ausführungsmechanismus von JS ist wie folgt:

(1) Alle Synchronisierungsaufgaben werden im Hauptthread ausgeführt, um einen Ausführungsstapel zu bilden.

(2) Zusätzlich zum Hauptthread gibt es auch eine „Aufgabenwarteschlange“. Solange die asynchrone Aufgabe das Operationsergebnis hat, wird ein Ereignis (Rückruffunktion) in die „Aufgabenwarteschlange“ gestellt.

(3) Sobald alle Synchronisierungsaufgaben im „Ausführungsstapel“ abgeschlossen sind, liest das System die „Aufgabenwarteschlange“, um zu sehen, welche Ereignisse darin enthalten sind. Die entsprechenden asynchronen Aufgaben beenden den Wartezustand. Betreten Sie den Ausführungsstapel und starten Sie die Ausführung.

(4) Der Hauptthread wiederholt ständig den dritten Schritt oben

Aufgabenwarteschlange

Wie oben erwähnt. Gehen Sie zu Aufgabenwarteschlange. Was genau ist die Aufgabenwarteschlange? Zum Beispiel

Im ES6-Standard ist die Aufgabenwarteschlange in Makroaufgaben (Makroaufgabe) und Mikroaufgaben (Mikroaufgabe) unterteilt.

1.Makroaufgabe enthält: Skript (ganz Code), setTimeout, setInterval, setImmediate, I/O, UI-Rendering

2.Micro-Task enthält: Process.nextTick, Promises, Object.observe, MutationObserver

Die Reihenfolge der Ereignisschleife besteht darin, die erste Schleife vom Skript aus zu starten und dann den globalen Kontext in den Funktionsaufrufstapel einzugeben und ihn an das Modul zu übergeben, das ihn verarbeitet . Nach der Verarbeitung wird die Rückruffunktion in die Makroaufgabe-Warteschlange gestellt. Wenn eine Mikroaufgabe auftritt, wird auch ihre Rückruffunktion in die Mikroaufgaben-Warteschlange gestellt. Bis der Funktionsaufrufstapel gelöscht ist und nur noch der globale Ausführungskontext übrig ist, werden alle Mikroaufgaben ausgeführt. Nachdem alle ausführbaren Mikroaufgaben ausgeführt wurden. Die Schleife führt erneut eine Aufgabenwarteschlange in der Makroaufgabe aus und führt dann nach der Ausführung alle Mikroaufgaben aus, und die Schleife wird fortgesetzt.

Als nächstes analysieren wir den Ausführungsprozess:

(function test() {
    setTimeout(function() {console.log(4)}, 0);
    new Promise(function executor(resolve) {
        console.log(1);
        for( var i=0 ; i<10000 ; i++ ) {
            i == 9999 && resolve();
        }
        console.log(2);
    }).then(function() {
        console.log(5);
    });
    console.log(3);
})()

1 Der globale Kontext wird auf den Stapel verschoben und der darin enthaltene Code wird ausgeführt.

2. Führen Sie setTimeout aus, übergeben Sie es als Makroaufgabe an das Timer-Modul und stellen Sie dann seine Rückruffunktion in eine eigene Warteschlange.

3. In der Promise-Instanz ausführen und das Promise auf den Stapel verschieben. Der erste Parameter besteht darin, die Ausgabe 1 in der aktuellen Aufgabe direkt auszuführen.

4. Führen Sie den Schleifenkörper aus, stoßen Sie auf die Auflösungsfunktion, schieben Sie sie in den Stapel und lassen Sie sie nach der Ausführung wieder herausspringen, ändern Sie den Versprechenstatus in „Erfüllt“ und geben Sie dann 2 aus.

5 Die then-Methode wird als Mikroaufgabe in die Promise-Aufgabenwarteschlange eingegeben.

6. Führen Sie den Code weiter aus und geben Sie 3 aus.

7. Nach der Ausgabe von 3 wird der erste Makrotask-Code ausgeführt und alle Mikrotasks in der Warteschlange beginnen mit der Ausführung. Die Rückruffunktion von Then wird auf den Stapel gelegt und dann herausgesprungen, wobei 5 ausgegeben wird.

8. Zu diesem Zeitpunkt sind alle Micao-Aufgaben abgeschlossen und der erste Zyklus endet. Die zweite Runde der Schleife beginnt mit der Rückruffunktion von setTimeout und wird in den Stapel verschoben. Zu diesem Zeitpunkt wird 4 ausgegeben.

Zusammenfassung:

1. Verschiedene Aufgaben werden in verschiedene Aufgabenwarteschlangen gestellt.

2. Führen Sie zuerst die Makroaufgabe aus, warten Sie, bis der Funktionsaufrufstapel gelöscht ist, und führen Sie dann alle Mikroaufgaben in der Warteschlange aus.

3. Warten Sie, bis alle Mikroaufgaben ausgeführt sind, und starten Sie dann die Ausführung aus einer Aufgabenwarteschlange in der Makroaufgabe, und die Schleife wird so fortgesetzt.

4. Wenn mehrere Makrotask-(Mikrotask-)Warteschlangen vorhanden sind, wird die Reihenfolge der Ereignisschleife in der oben in der Makrotask-(Mikrotask)-Klassifizierung angegebenen Reihenfolge ausgeführt.

Zusammenfassung:

Wenn die JS-Engine den JS-Code analysiert, erstellt sie einen Hauptthread und einen Aufrufstapel (call -stack): Wenn eine Aufgabe in einem Aufrufstapel verarbeitet wird, müssen andere warten.

Wenn einige asynchrone Vorgänge ausgeführt werden, werden sie zur Verarbeitung an andere Module des Browserkernels übergeben (am Beispiel des Webkits handelt es sich um das Webcore-Modul Nach der Verarbeitung). Wenn die Aufgabe abgeschlossen ist (Rückruffunktion), wird sie in die Aufgabenwarteschlange gestellt.

Im Allgemeinen werden die Rückruffunktionen verschiedener asynchroner Aufgaben in verschiedene Aufgabenwarteschlangen gestellt. Nachdem alle Aufgaben im Aufrufstapel ausgeführt wurden, werden die Aufgaben in der Aufgabenwarteschlange (Rückruffunktionen) angezeigt. wird ausgeführt. )

Empfohlene verwandte Artikel:

Verwendung dieses Schlüsselworts in Javascript (mit Code)

Was sind die js-Datentypen? Zusammenfassung der Datentypen von js

Das obige ist der detaillierte Inhalt vonJS-Betriebsmechanismus: Analyse der Synchronisation, Asynchronität und Ereignisschleife (Ereignisschleife). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn