Heim >Web-Frontend >js-Tutorial >Detaillierte Erläuterung des Browser-Multithreading-Mechanismus

Detaillierte Erläuterung des Browser-Multithreading-Mechanismus

php中世界最好的语言
php中世界最好的语言Original
2018-03-16 15:20:211607Durchsuche

Dieses Mal werde ich Ihnen den Multithreading-Mechanismus des Browsers ausführlich erläutern. Was sind die Vorsichtsmaßnahmen, wenn Sie den Multithreading-Mechanismus des Browsers verwenden?

Bevor wir sprechen, weiß jeder, dass js auf einem einzelnen Thread basiert und dieser Thread die js-Engine des Browsers ist.
Werfen wir zunächst einen Blick auf die Threads, die jeder in seinem Browser verwendet.

Wenn wir einige zeitaufwändige Vorgänge ausführen möchten, z. B. das Laden eines großen Bildes, benötigen wir möglicherweise einen Fortschrittsbalken, damit der Benutzer während des gesamten Wartevorgangs warten kann Der js-Thread wird blockiert und der nachfolgende Code kann nicht normal ausgeführt werden, was die Benutzererfahrung erheblich beeinträchtigen kann. Zu diesem Zeitpunkt gehen wir davon aus, dass wir über einen Arbeitsthread verfügen, der diese zeitaufwändigen Vorgänge abwickelt. Im traditionellen HTML-Zeitalter war das im Grunde unmöglich zu erreichen, aber jetzt haben wir etwas, das man einen Worker nennt. Es ist eine Klasse in js und wir müssen nur eine Instanz davon erstellen, um sie zu verwenden.

var worker = new Worker(js file path);

Konstruieren Sie die Parameter der -Funktion und geben Sie den Pfad Ihrer js-Datei ein. Diese js-Datei wird im Gegensatz zur ursprünglichen js-Datei in einem neu geöffneten Thread des Browsers ausgeführt Threads sind nicht betroffen.

Da sie sich also nicht gegenseitig beeinflussen, wie kommunizieren die beiden Threads eigentlich bereits im Code, nämlich in den beiden Funktionen onPostMessage (Daten). ) sind Sie Die zu übergebenden Daten und onmessage sind eine Rückruffunktion . Onmessage verfügt nur über einen versteckten Parameter, nämlich event.data um die übergebenen eingehenden Daten zu erhalten, werden sie zum Aktualisieren des Hauptthreads verwendet.

JavaScripts setTimeout und setInterval sind zwei Methoden, die die Gefühle anderer leicht täuschen können, weil wir oft denken, dass sie, wenn sie aufgerufen werden, meiner Meinung nach auf die etablierte Weise ausgeführt werden Ich bin mir dessen zutiefst bewusst, zum Beispiel

[Javascript]Einzelexemplar anzeigen, drucken?Detaillierte Erläuterung des Browser-Multithreading-MechanismusDetaillierte Erläuterung des Browser-Multithreading-Mechanismus

  1. setTimeout( function() { alarm('Hello!'); } , 0);

  2. setInterval( callbackFunction , 100);

denken Die Begrüßungsmethode in setTimeout wird sofort ausgeführt, da dies nicht aus der Luft gegriffen ist, sondern das JavaScript-API-Dokument die Bedeutung des zweiten Parameters klar als die Anzahl der Millisekunden definiert, nach denen es folgt Die Callback-Methode wird hier natürlich auf 0 Millisekunden gesetzt. Sie wurde sofort ausgeführt.
Ebenso habe ich keinen Zweifel daran, dass die CallbackFunction-Methode von setInterval sofort alle 100 Millisekunden ausgeführt wird!


Aber da die Erfahrung in der Entwicklung von JavaScript-Anwendungen immer größer und reicher wird, werde ich eines Tages einen seltsamen Codeabschnitt finden und ihn nicht verstehen können:

[Javascript]

Einfache Kopie anzeigen, drucken?Detaillierte Erläuterung des Browser-Multithreading-MechanismusDetaillierte Erläuterung des Browser-Multithreading-Mechanismus

    p.onclick = function(){
  1. setTimeout( function(){document .getElementById('inputField').focus();}, 0);
  2. }; Warum setTimeout nach 0 Millisekunden verwenden? In diesem Moment beginnt der feste Glaube zu schwanken.
  3. Bis zum letzten Tag haben Sie versehentlich einen schlechten Code geschrieben:

[ Javascript]
Einfache Kopie anzeigen, drucken?


  1. setTimeout( function(){ while(true){} } , 100);

  2. setTimeout( function(){ warning('Hallo! ' ); } , 200);

  3. setInterval( callbackFunction , 200);

Die erste Codezeile tritt in eine Endlosschleife ein , aber bald werden Sie feststellen, dass die zweite und dritte Zeile nicht Ihren Erwartungen entsprechen, die Alarmbegrüßung nicht angezeigt wurde und es keine Neuigkeiten von callbacKFunction gibt.

Zu diesem Zeitpunkt sind Sie völlig verwirrt Es ist schwer zu akzeptieren, denn der Prozess, alte Erkenntnisse zu ändern, um neue Ideen zu akzeptieren, ist schmerzhaft, aber die Fakten liegen vor unseren Augen, und die Suche nach der Wahrheit von JavaScript wird wegen des Schmerzes nicht aufhören JavaScript-Thread und Timer-Erkundungsreise!

Öffnen Sie die Wolken und sehen Sie das Mondlicht

Der Hauptgrund für alle oben genannten Missverständnisse ist: Unterbewusst zu glauben, dass es mehrere JavaScript-Engines gibt Der Thread wird ausgeführt und die Timer-Rückruffunktion von JavaScript wird asynchron ausgeführt.

Tatsächlich verwendet JavaScript die meiste Zeit eine Blendungsmethode, um unsere Augen zu täuschen. Die Hintergrundbeleuchtung hier muss eine Tatsache verdeutlichen:

Die JavaScript-Engine läuft in einem einzigen Thread. Der Browser hat immer nur einen Thread, der das JavaScript-Programm ausführt.

Die JavaScript-Engine verwendet Single-. Der Thread-Betrieb ist ebenfalls sinnvoll und muss sich nicht um komplexe Probleme wie die Thread-Synchronisierung kümmern, und das Problem wird vereinfacht.

Wie arbeitet die Single-Threaded-JavaScript-Engine bei der Verarbeitung mit dem Browser-Kernel zusammen? Diese Timer und reagieren auf Browser-Ereignisse?
Das Folgende ist eine kurze Erklärung basierend auf der Browser-Kernel-Verarbeitungsmethode.

Die Browser-Kernel-Implementierung ermöglicht die asynchrone Ausführung dieser Threads Andere unterliegen der Kernel-Kontrolle, um die Synchronisierung aufrechtzuerhalten. Die Implementierung des Browser-Kernels verfügt über mindestens drei residente Threads: einen JavaScript-Engine-Thread, einen Schnittstellen-Rendering-Thread und einen Browser-Ereignis-auslösenden Thread B. HTTP-Anforderungsthreads, generieren unterschiedliche asynchrone Ereignisse. Das folgende Diagramm zeigt, wie eine Single-Thread-JavaScript-Engine mit anderen Threads interagiert und kommuniziert Die Prinzipien sind ähnlich.

Wie aus dem Bild ersichtlich ist, ist die JavaScript-Engine im Browser ereignisgesteuert. Die Ereignisse können hier als verschiedene ihr zugewiesene Aufgaben angesehen werden Diese Aufgaben können vom Browser stammen. Der aktuell von der Engine ausgeführte Codeblock, z. B. der Aufruf von setTimeout zum Hinzufügen einer Aufgabe, kann auch von anderen Threads im Browser-Kernel stammen, z. B. von Mausklickereignissen für Schnittstellenelemente 🎜> löst Benachrichtigungen über die Ankunftszeit, Benachrichtigungen über asynchrone Anforderungsstatusänderungen usw. aus. Aus Codesicht sind Aufgabenentitäten verschiedene Rückruffunktionen. Die JavaScript-Engine wartet auf das Eintreffen von Aufgaben in der Aufgabenwarteschlange Bei einer Single-Thread-Beziehung müssen diese Aufgaben nacheinander in die Warteschlange gestellt und von der Engine verarbeitet werden. Die obige Abbildung t1-t2..tn stellt verschiedene Zeitpunkte dar. Das entsprechende kleine Quadrat unter tn stellt die Aufgabe dar Angenommen, es ist der Zeitpunkt t1 und die Engine läuft im Taskblockcode, der t1 entspricht. Beschreiben wir zu diesem Zeitpunkt den Status anderer Threads im Browserkernel t1-Zeit:

GUI-Rendering-Thread:

Dieser Thread ist für das Rendern der Browseroberfläche HTML-Element verantwortlich, wenn die Schnittstelle neu gezeichnet werden muss (Repaint) oder wenn ein Reflow durch einen Vorgang verursacht wird, wird dieser Thread ausgeführt. Obwohl sich dieser Artikel auf die Erläuterung des JavaScript-Timing-Mechanismus konzentriert, ist es an dieser Stelle notwendig, darüber zu sprechen. Der Rendering-Thread schließt sich gegenseitig mit dem JavaScript-Engine-Thread aus ist leicht zu verstehen, da JavaScript-Skripte DOM-Elemente bearbeiten und gleichzeitig die Schnittstelle rendern können. Die vor und nach dem Rendering-Thread erhaltenen Elementdaten sind möglicherweise inkonsistent >

Während die JavaScript-Engine das Skript ausführt, befindet sich der Browser-Rendering-Thread in einem angehaltenen Zustand, was bedeutet, dass er „eingefroren“ ist.

Daher, wenn Sie Aktualisierungsvorgänge durchführen B. das Hinzufügen von Knoten, das Löschen von Knoten oder das Ändern des Erscheinungsbilds von Knoten, werden die Aktualisierungen nicht sofort in einer Warteschlange gespeichert, bis die JavaScript-Engine inaktiv ist eine Chance, es zu rendern.

GUI-Ereignis auslösender Thread:

Die Ausführung des JavaScript-Skripts hat keinen Einfluss auf das Auslösen von HTML-Elementereignissen. Während des Zeitraums t1 klickt der Benutzer zunächst auf eine Maustaste. Der Klick wird vom Browserereignis-auslösenden Thread erfasst und bildet ein Mausklickereignis Aus der Abbildung ist ersichtlich, dass dieses Ereignis für den JavaScript-Engine-Thread von anderen Threads asynchron an das Ende der Aufgabenwarteschlange übertragen wird. Da die Engine die Aufgabe bei t1 verarbeitet, wartet dieses Mausklickereignis auf die Verarbeitung.

Timing-Trigger-Thread:

Beachten Sie, dass der Timing-Zähler des Browsermodells hier nicht von der JavaScript-Engine gezählt wird, da die JavaScript-Engine Single-Threaded ist. Es kann die Zeit nicht zählen und das Timing auslösen, daher ist das Timing-Ereignis auch ein asynchrones Ereignis.

Wie aus der Abbildung hervorgeht, ist die Zeitspanne t1 Nachdem das Mausklickereignis ausgelöst wurde, ist auch das zuvor festgelegte setTimeout-Timing erreicht. Zu diesem Zeitpunkt generiert der auslösende Thread ein asynchrones zeitgesteuertes Ereignis und stellt es in die Aufgabenwarteschlange der Click-Event-Callback und wartet auf die Verarbeitung.
In ähnlicher Weise wird noch innerhalb des t1-Zeitraums ein bestimmter setInterval-Timer als nächstes aufgerufen. Aufgrund des Intervall-Timings wurde er innerhalb des t1-Zeitraums zweimal hintereinander ausgelöst, und zwar Zwei Ereignisse wurden bis zum Ende der Warteschlange zur Verarbeitung eingereiht.

Es ist ersichtlich, dass der Timing-Trigger-Thread kontinuierlich asynchron generiert, wenn der Zeitraum t1 sehr lang ist, viel größer als setInterval Timing-Ereignisse werden an das Ende der Aufgabenwarteschlange gestellt, unabhängig davon, ob sie verarbeitet wurden. Sobald jedoch t1 und die Aufgaben vor dem ersten Timing-Ereignis verarbeitet wurden, werden die Aufgaben in diesen Anordnungen nacheinander ausgeführt Dies liegt daran, dass für die JavaScript-Engine jede Aufgabe in der Verarbeitungswarteschlange auf die gleiche Weise verarbeitet wird, die Reihenfolge der Verarbeitung jedoch unterschiedlich ist.

Nach t1Das heißt, die aktuell verarbeitete Die Aufgabe wurde zurückgegeben. Die JavaScript-Engine überprüft die Aufgabenwarteschlange und stellt fest, dass die aktuelle Warteschlange nicht leer ist. Daher wird die entsprechende Aufgabe unter t2 ausgeführt und so weiter.

Wenn die Warteschlange nicht leer ist, entnimmt die Engine eine Aufgabe vom Kopf der Warteschlange, bis die Aufgabe verarbeitet ist, d. h. nach der Rückkehr führt die Engine die nächste aus Aufgabe. Andere Aufgaben in der Warteschlange können nicht ausgeführt werden, bevor die Aufgabe zurückgegeben wird.

Ich glaube, Sie haben jetzt eine klare Vorstellung davon, ob JavaScript multithreading sein kann, und verstehen es auch Lassen Sie uns einige Fälle analysieren:

Fall 1: setTimeout und setInterval

[Javascript]Einfache Kopie anzeigen, drucken?Detaillierte Erläuterung des Browser-Multithreading-MechanismusDetaillierte Erläuterung des Browser-Multithreading-Mechanismus

  1. setTimeout(function(){

  2. /* Codeblock... */

  3. setTimeout(arguments.callee, 10);

  4. }, 10); 🎜>

  5. /*Codeblock... */


  6. }, 10);
  7. Dies Die beiden Codeteile scheinen zusammen den gleichen Effekt zu haben, aber tatsächlich sind sie es nicht. Das setTimeout in der Callback-Funktion im ersten Teil dient dazu, ein neues setTimeout-Timing festzulegen, nachdem die JavaScript-Engine ausgeführt wurde. Angenommen, es gibt ein Zeitintervall vom Abschluss des vorherigen Rückrufs bis zum Beginn des nächsten Rückrufs. Theoretisch beträgt das Ausführungszeitintervall zwischen zwei setTimeout-Rückrufen. Im zweiten Abschnitt, nachdem setInterval das Timing festgelegt hat Der Timing-Trigger-Thread wird weiterhin alle zehn Sekunden ausgelöst, um ein asynchrones zeitgesteuertes Ereignis zu generieren und es an das Ende der Aufgabenwarteschlange zu stellen. Theoretisch beträgt das Ausführungszeitintervall zwischen zwei setInterval-Rückrufen

    Fall 2: Ist die asynchrone Ajax-Anfrage wirklich asynchron?
  8. Viele Klassenkameraden und Freunde sind verwirrt, da JavaScript angeblich in einem einzelnen Thread ausgeführt wird. Ist XMLHttpRequest nach der Verbindung wirklich asynchron?

    Tatsächlich ist die Anfrage zwar asynchron, aber diese Anfrage wird vom Browser neu geöffnet. Eine Thread-Anfrage (siehe Abbildung oben). Wenn sich der angeforderte Status ändert und zuvor ein Rückruf festgelegt wurde, generiert der asynchrone Thread einen Status Ändern Sie das Ereignis und stellen Sie es in die Verarbeitungswarteschlange der JavaScript-Engine, um auf die Verarbeitung zu warten. Es handelt sich um eine in einem Thread ausgeführte Rückruffunktion. Insbesondere handelt es sich um eine Funktion, die von einem einzelnen Thread festgelegt wird, der onreadystatechange ausführt .
Ich glaube, dass Sie die Methode beherrschen, nachdem Sie den Fall in diesem Artikel gelesen haben. Weitere spannende Informationen finden Sie in anderen verwandten Artikeln auf der chinesischen PHP-Website.

Empfohlene Lektüre:

Die Verwendung von Single-Threaded-JS und Multi-Threaded-Browsern

Einige kleinere Probleme bei der Typkonvertierung in JS

Anzeigetypkonvertierung in JS

So implementieren Sie horizontales Scrollen und schwebende Navigation in JS

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung des Browser-Multithreading-Mechanismus. 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