Geekflare wird von unserem Publikum unterstützt. Wir können Affiliate-Provisionen durch den Kauf von Links auf dieser Website verdienen.
Teilen:

Wie funktioniert die Ereignisschleife in JavaScript?

Javascript-Schleife
Invicti Web Application Security Scanner – die einzige Lösung, die eine automatische Verifizierung von Schwachstellen mit Proof-Based Scanning™ bietet.

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 häufig 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 EREIGNISSCHLEIFE!. 

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

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

What is 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 interpretierte, nicht blockierende, asynchrone, gleichzeitige Sprache mit einem Thread.

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

Lass es uns zusammenfassen!

Die Schlüsselwörter hier in Bezug auf diesen Artikel sind Single-Threaded, nicht blockierend, gleichzeitig, funktioniert 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 gleichzeitig?

Aber was bedeutet Blockieren?

Nicht blockierende

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 im Thread nicht langsam sind.

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? dh seinen Code mit mehr als einem Thread ausführen?

asynchrone

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 die Warteschlange das Ergebnis der Blockierungsvorgänge 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 Obige geben.

  • JavaScript ist Single-Threaded
  • JavaScript ist nicht blockierend, dh langsame Prozesse blockieren seine Ausführung nicht
  • JavaScript ist gleichzeitig, dh es führt seinen Code in mehr als einem Thread gleichzeitig aus
  • JavaScript ist asynchron, dh es führt Blockierungscode an einer anderen Stelle aus.

Aber das oben Genannte passt 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 gibt es einige versteckte Threads, die uns nicht bekannt sind.

V8-Engine

Die V8-Engine ist eine leistungsstarke Open-Source-Laufzeit-Engine für Webassemblierungen 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

Wie läuft JavaScript dann gleichzeitig und asynchron ab, ohne den Hauptausführungsthread zu blockieren, da V8 nur einen Aufrufstapel hat?

Versuchen wir dies herauszufinden, indem wir einen einfachen, aber allgemeinen 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 die letzte Zeile ausgeführt wird?

Ein anderer Thread scheint uns dabei geholfen zu haben, dieses Timeout 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 genau den Spezifikationen für Ecma-Skripte, und verschiedene Versionen davon werden häufig gemäß den Ecma-Skriptspezifikationen (ES X) bezeichnet.

Execution Workflow

Ereignisse, Timer und Ajax-Anforderungen werden von den Browsern auf der Clientseite 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 aufrufen printSquare() wird es auf den Call Stack geschoben, der printSquare() Funktion ruft die quadratisch() Funktion. Der square() Funktion wird auf den Stapel geschoben und ruft auch die multiply() Funktion. 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 vom Stapel entfernt, gefolgt von der square() Funktion und dann die printSquare() Funktion.

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.

Gehen wir zurück zu unserem setTimeout Beispiel oben;

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 verarbeitet 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 auf magische Weise wieder 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 in 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 aus der Task-Warteschlange 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.

Conclusion

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.

Danke an unsere Sponsoren
Weitere großartige Lektüre zum Thema Entwicklung
Treiben Sie Ihr Geschäft an
Einige der Tools und Dienste, die Ihr Unternehmen beim Wachstum unterstützen.
  • Invicti verwendet das Proof-Based Scanning™, um die identifizierten Schwachstellen automatisch zu verifizieren und innerhalb weniger Stunden umsetzbare Ergebnisse zu generieren.
    Versuchen Sie es mit Invicti
  • Web-Scraping, Wohn-Proxy, Proxy-Manager, Web-Unlocker, Suchmaschinen-Crawler und alles, was Sie zum Sammeln von Webdaten benötigen.
    Versuchen Sie es mit Brightdata
  • Semrush ist eine All-in-One-Lösung für digitales Marketing mit mehr als 50 Tools in den Bereichen SEO, Social Media und Content-Marketing.
    Versuchen Sie es mit Semrush
  • Intruder ist ein Online-Schwachstellenscanner, der Cyber-Sicherheitslücken in Ihrer Infrastruktur findet, um kostspielige Datenschutzverletzungen zu vermeiden.
    MIT DER INTELLIGENTEN SCHADENKALKULATION VON Intruder