Wie funktioniert die Ereignisschleife in JavaScript?

Während es möglicherweise ein gründliches Verständnis von Sprachen wie C ++ und C erfordert, um vollständigen Produktionscode zu schreiben, kann JavaScript oft nur mit einem grundlegenden Verständnis dessen geschrieben werden, was mit der Sprache getan werden kann.


Konzepte wie das Übergeben von Rückrufen an Funktionen oder das Schreiben von asynchronem Code sind oft nicht so schwierig zu implementieren, weshalb sich die meisten JavaScript-Entwickler weniger darum kümmern, was unter der Haube vor sich geht. Es ist ihnen einfach egal, welche Komplexität sie durch die Sprache tief abstrahiert haben.

Als JavaScript-Entwickler wird es immer wichtiger zu verstehen, was wirklich unter der Haube passiert und wie die meisten dieser von uns abstrahierten Komplexitäten wirklich funktionieren. Dies hilft uns, fundiertere Entscheidungen zu treffen, was wiederum die Codeleistung drastisch steigern kann.

Dieser Artikel konzentriert sich auf eines der sehr wichtigen, aber selten verstandenen Konzepte oder Begriffe in JavaScript. Das EVENT LOOP!. 

Das Schreiben von asynchronem Code kann in JavaScript nicht vermieden werden. Warum bedeutet ein asynchron ausgeführter Code wirklich? d.h.. Die Ereignisschleife

Bevor wir verstehen können, wie die Ereignisschleife funktioniert, müssen wir zunächst verstehen, was JavaScript selbst ist und wie es funktioniert!

Was ist JavaScript??

Bevor wir fortfahren, möchte ich, dass wir einen Schritt zurück zu den Grundlagen machen. Was ist JavaScript wirklich? Wir könnten JavaScript definieren als;

JavaScript ist eine hochqualifizierte, interpretierte, nicht blockierende, asynchrone, gleichzeitige Sprache mit einem Thread.

Warten Sie, was ist das? Eine buchstäbliche Definition? ��

Lassen Sie es uns zusammenfassen!

Die Schlüsselwörter hier in Bezug auf diesen Artikel sind Single-Threaded, nicht blockierend, gleichzeitig, und asynchron.

Einzelfaden

Ein Ausführungsthread ist die kleinste Folge programmierter Anweisungen, die von einem Scheduler unabhängig verwaltet werden kann. Eine Programmiersprache ist Single-Threaded, dh sie kann jeweils nur eine Aufgabe oder Operation ausführen. Dies bedeutet, dass ein gesamter Prozess von Anfang bis Ende ausgeführt wird, ohne dass der Thread unterbrochen oder gestoppt wird.

Im Gegensatz zu Multithread-Sprachen, in denen mehrere Prozesse gleichzeitig auf mehreren Threads ausgeführt werden können, ohne sich gegenseitig zu blockieren.

Wie kann JavaScript Single-Threaded sein und nicht blockierend zur selben Zeit?

Aber was bedeutet Blockieren??

Nicht blockierend

Es gibt keine einzige Definition für Blockierung. es bedeutet einfach nur Dinge, die langsam auf dem Faden laufen. Nicht blockieren bedeutet also Dinge, die den Thread nicht verlangsamen.

Aber warte, habe ich gesagt, dass JavaScript auf einem einzelnen Thread ausgeführt wird? Und ich sagte auch, dass es nicht blockierend ist, was bedeutet, dass die Aufgabe schnell auf dem Aufrufstapel ausgeführt wird? Aber wie??? Wie wäre es, wenn wir Timer laufen lassen? Schleifen?

Entspannen! Wir würden es gleich herausfinden ��.

Gleichzeitig

Parallelität bedeutet, dass der Code gleichzeitig von mehr als einem Thread ausgeführt wird.

Okay, die Dinge werden wirklich seltsam Wie kann JavaScript nun Single-Threaded sein und gleichzeitig ausgeführt werden? Ausführen seines Codes mit mehr als einem Thread?

Asynchron

Asynchrone Programmierung bedeutet, dass der Code in einer Ereignisschleife ausgeführt wird. Wenn eine Blockierungsoperation vorliegt, wird das Ereignis gestartet. Der Blockierungscode wird weiterhin ausgeführt, ohne den Hauptausführungsthread zu blockieren. Wenn der Blockierungscode nicht mehr ausgeführt wird, ist er das Ergebnis der Blockierungsvorgänge in der Warteschlange und schiebt sie zurück auf den Stapel.

Aber JavaScript hat einen einzigen Thread? Was führt dann diesen Blockierungscode aus, während andere Codes im Thread ausgeführt werden??

Bevor wir fortfahren, lassen Sie uns einen Rückblick auf das oben Gesagte geben.

  • JavaScript ist Single-Threaded
  • JavaScript blockiert nicht, d. H. Langsame Prozesse blockieren die Ausführung nicht
  • JavaScript ist gleichzeitig, d. H. Es führt seinen Code gleichzeitig in mehr als einem Thread aus
  • JavaScript ist asynchron, d. H. Es führt Blockierungscode an einer anderen Stelle aus.

Das oben Gesagte passt jedoch nicht genau zusammen. Wie kann eine Single-Threaded-Sprache nicht blockierend, gleichzeitig und asynchron sein??

Gehen wir etwas tiefer, gehen wir zu den JavaScript-Laufzeit-Engines V8 über. Vielleicht enthält sie einige versteckte Threads, die uns nicht bekannt sind.

V8 Motor

Die V8-Engine ist eine leistungsstarke Open-Source-Webassembly-Laufzeit-Engine für JavaScript, die von Google in C ++ geschrieben wurde. Die meisten Browser führen JavaScript mit der V8-Engine aus, und selbst die beliebte Laufzeitumgebung des Knotens js verwendet es.

In einfachem Englisch ist V8 ein C ++ – Programm, das JavaScript-Code empfängt, kompiliert und ausführt.

Der V8 macht zwei wichtige Dinge;

  • Heap-Speicherzuordnung
  • Aufrufstapel-Ausführungskontext

Leider war unser Verdacht falsch. Der V8 hat nur einen Aufrufstapel. Stellen Sie sich den Aufrufstapel als Thread vor.

Ein Thread === ein Aufrufstapel === jeweils eine Ausführung.

Bild – Hacker Mittag

Da V8 nur einen Aufrufstapel hat, wird JavaScript dann gleichzeitig und asynchron ausgeführt, ohne den Hauptausführungsthread zu blockieren?

Versuchen wir dies herauszufinden, indem wir einen einfachen, aber gemeinsamen asynchronen Code schreiben und ihn gemeinsam analysieren.

JavaScript führt jeden Code zeilenweise nacheinander aus (Single-Threaded). Wie erwartet wird hier die erste Zeile in der Konsole gedruckt, aber warum wird die letzte Zeile vor dem Timeout-Code gedruckt? Warum wartet der Ausführungsprozess nicht auf den Timeout-Code (Blockieren), bevor er die letzte Zeile ausführt??

Ein anderer Thread scheint uns dabei geholfen zu haben, dieses Zeitlimit auszuführen, da wir ziemlich sicher sind, dass ein Thread zu einem bestimmten Zeitpunkt nur eine einzige Aufgabe ausführen kann.

Werfen wir einen kurzen Blick in die V8 Quellcode für eine Weile.

Warte was??!!! Es gibt keine Timer-Funktionen in V8, kein DOM? Keine Ereignisse? Kein AJAX?…. Yeeeeessss!!!

Ereignisse, DOM, Timer usw. sind nicht Teil der Kernimplementierung von JavaScript. JavaScript entspricht strikt den Ecma-Skriptspezifikationen, und verschiedene Versionen davon werden häufig gemäß den Ecma-Skriptspezifikationen (ES X) bezeichnet..

Ausführungsworkflow

Ereignisse, Timer und Ajax-Anforderungen werden alle clientseitig von den Browsern bereitgestellt und häufig als Web-API bezeichnet. Sie sind diejenigen, die es ermöglichen, dass das JavaScript mit einem Thread nicht blockierend, gleichzeitig und asynchron ist! Aber wie?

Der Ausführungsworkflow eines JavaScript-Programms besteht aus drei Hauptabschnitten: dem Aufrufstapel, der Web-API und der Task-Warteschlange.

Der Call Stack

Ein Stapel ist eine Datenstruktur, in der das zuletzt hinzugefügte Element immer das erste ist, das aus dem Stapel entfernt wird. Sie können sich dies als Stapel einer Platte vorstellen, in der nur die erste Platte, die zuletzt hinzugefügt wurde, zuerst entfernt werden kann. Ein Call Stack ist einfach nichts anderes als eine Stack-Datenstruktur, in der Aufgaben oder Code entsprechend ausgeführt werden.

Betrachten wir das folgende Beispiel.

Quelle – https://youtu.be/8aGhZQkoFbQ

Wenn Sie die Funktion printSquare () aufrufen, wird sie auf den Aufrufstapel verschoben. Die Funktion printSquare () ruft die Funktion square () auf. Die Funktion square () wird auf den Stapel verschoben und ruft auch die Funktion multiply () auf. Die Multiplikationsfunktion wird auf den Stapel geschoben. Da die Multiplikationsfunktion zurückkehrt und das letzte ist, was auf den Stapel verschoben wurde, wird sie zuerst aufgelöst und aus dem Stapel entfernt, gefolgt von der Funktion square () und dann der Funktion printSquare ().

Die Web-API

Hier wird Code ausgeführt, der nicht von der V8-Engine verarbeitet wird, um den Hauptausführungsthread nicht zu blockieren. Wenn der Call Stack auf eine Web-API-Funktion stößt, wird der Prozess sofort an die Web-API übergeben, wo er ausgeführt wird, und der Call Stack kann während seiner Ausführung andere Vorgänge ausführen.

Kehren wir zu unserem obigen setTimeout-Beispiel zurück.

Wenn wir den Code ausführen, wird die erste console.log-Zeile in den Stack verschoben und wir erhalten unsere Ausgabe fast sofort. Wenn das Timeout erreicht ist, werden die Timer vom Browser verwaltet und sind nicht Teil der Kernimplementierung von V8. Sie werden verschoben Stattdessen wird der Stack freigegeben, damit andere Vorgänge ausgeführt werden können.

Während das Timeout noch ausgeführt wird, fährt der Stack mit der nächsten Aktionszeile fort und führt das letzte console.log aus. Dies erklärt, warum dieses vor der Timer-Ausgabe ausgegeben wird. Sobald der Timer abgelaufen ist, passiert etwas. Die Konsole.log in dann Timer erscheint wieder magisch im Aufrufstapel!

Wie?

Die Ereignisschleife

Bevor wir uns mit der Ereignisschleife befassen, gehen wir zunächst die Funktion der Task-Warteschlange durch.

Zurück zu unserem Timeout-Beispiel: Sobald die Web-API die Ausführung der Aufgabe abgeschlossen hat, wird sie nicht einfach automatisch auf den Call Stack zurückgeschoben. Es geht zum Task-Warteschlange. 

Eine Warteschlange ist eine Datenstruktur, die nach dem First-in-First-out-Prinzip arbeitet. Wenn also Aufgaben in die Warteschlange verschoben werden, werden sie in derselben Reihenfolge ausgegeben. Aufgaben, die von den Web-APIs ausgeführt wurden und in die Task-Warteschlange verschoben werden, kehren dann zum Aufrufstapel zurück, um das Ergebnis auszudrucken.

Aber warte. Was zum Teufel ist die Event-Schleife???

Quelle – https://youtu.be/8aGhZQkoFbQ

Die Ereignisschleife ist ein Prozess, der darauf wartet, dass der Aufrufstapel gelöscht wird, bevor Rückrufe von der Taskwarteschlange in den Aufrufstapel übertragen werden. Sobald der Stapel gelöscht ist, wird die Ereignisschleife ausgelöst und überprüft die Task-Warteschlange auf verfügbare Rückrufe. Wenn es welche gibt, wird sie in den Call Stack verschoben, wartet, bis der Call Stack wieder gelöscht ist, und wiederholt den gleichen Vorgang.

Quelle – https://www.quora.com/How-does-an-event-loop-work/answer/Timothy-Maxwell

Das obige Diagramm zeigt den grundlegenden Workflow zwischen der Ereignisschleife und der Taskwarteschlange.

Fazit

Obwohl dies eine sehr grundlegende Einführung ist, bietet das Konzept der asynchronen Programmierung in JavaScript genügend Einblicke, um klar zu verstehen, was unter der Haube vor sich geht und wie JavaScript mit nur einem Thread gleichzeitig und asynchron ausgeführt werden kann.

JavaScript ist immer auf Abruf verfügbar, und wenn Sie neugierig sind, würde ich Ihnen raten, dies zu überprüfen Udemy natürlich.

Jeffrey Wilson Administrator
Sorry! The Author has not filled his profile.
follow me
    Like this post? Please share to your friends:
    Adblock
    detector
    map