Inhaltsverzeichnis
Erklären wir zunächst, was die Ereignisschleife ist:
Hier kommt also die Frage. Welche Aufgabe sollte zuerst ausgeführt werden, wenn sich viele Aufgaben in der Aufgabenwarteschlange befinden?
Hinweis:
Heim Web-Frontend js-Tutorial Detaillierte Erläuterung von Beispielen für die js-Ereignisschleife

Detaillierte Erläuterung von Beispielen für die js-Ereignisschleife

Jun 26, 2017 am 09:17 AM
javascript 事件 循环

Ich habe schon einige Event-Loop-Blogs gelesen, aber nachdem ich sie eine Weile nicht gelesen hatte, wurde mir klar, dass ich sie alle vergessen hatte, also beschloss ich, einen Blog zu schreiben, um sie zusammenzufassen!

Erklären wir zunächst, was die Ereignisschleife ist:

Soweit wir wissen, ist das Js des Browsers Single-Threaded, d. h Beispielsweise wird höchstens ein Codesegment gleichzeitig ausgeführt, aber der Browser kann asynchrone Anfragen sehr gut verarbeiten. Warum also? Schauen wir uns zunächst ein Bild an
Detaillierte Erläuterung von Beispielen für die js-Ereignisschleife
Auf dem obigen Bild können wir sehen, dass der js-Hauptthread einen Ausführungsstapel hat und der gesamte js-Code im Ausführungsstapel ausgeführt wird. Wenn Sie während der Ausführung des Codes auf asynchronen Code stoßen (z. B. setTimeout, Ajax, Promise.then und Benutzerklicks usw.), fügt der Browser diese Codes in einen Thread ein (hier nennen wir ihn „Behind-the“) -Szenen-Thread). Durch Warten wird die Ausführung des Hauptthreads nicht blockiert Wenn auf die Anfrage geantwortet wird, wird sie vom Thread verarbeitet. Die Rückruffunktion wird in die Aufgabenwarteschlange gestellt und wartet auf die Ausführung. Wenn der Hauptthread mit der Ausführung des gesamten Codes im Stapel fertig ist, prüft er, ob eine auszuführende Aufgabe in der Aufgabenwarteschlange vorhanden ist. Wenn eine auszuführende Aufgabe vorhanden ist, wird die Aufgabe gestellt zur Ausführung in den Ausführungsstapel. Wenn die aktuelle Aufgabenwarteschlange leer ist, wartet sie in einer Schleife weiter auf das Eintreffen der Aufgabe. Daher wird dies als Ereignisschleife bezeichnet.

Hier kommt also die Frage. Welche Aufgabe sollte zuerst ausgeführt werden, wenn sich viele Aufgaben in der Aufgabenwarteschlange befinden?

Tatsächlich (wie im Bild oben gezeigt) verfügt js über zwei Aufgabenwarteschlangen, eine heißt Makrotask-Warteschlange (Aufgabenwarteschlange) und die andere heißt Mikrotask-Warteschlange

  • Ersteres wird hauptsächlich für relativ umfangreiche Arbeiten verwendet. Zu den häufigsten gehören setTimeout, setInterval, Benutzerinteraktionsvorgänge, UI-Rendering usw.

  • Letzteres wird hauptsächlich für relativ kleine Arbeiten verwendet, was häufig vorkommt. Es gibt Promise, process.nextTick (nodejs)

Was sind also die spezifischen Unterschiede zwischen den beiden? , wenn zwei Aufgaben gleichzeitig erscheinen, welche sollte ausgewählt werden?
Tatsächlich macht die Ereignisschleife Folgendes:

  1. Überprüfen Sie, ob die Makrotask-Warteschlange leer ist . Wenn nicht, fahren Sie mit dem nächsten Schritt fort, springen Sie zu 3

  2. Nehmen Sie die erste Aufgabe aus der Makrotask-Warteschlange (mit der längsten Zeit in der Warteschlange) und führen Sie sie aus im Ausführungsstapel (nur einer). Fahren Sie nach der Ausführung mit dem nächsten Schritt fort

  3. Überprüfen Sie, ob die Microtask-Warteschlange leer ist. Wenn nicht, fahren Sie mit dem nächsten Schritt fort, andernfalls springen Sie zu 1 (eine neue Ereignisschleife starten)

  4. Aus der Mikrotask-Warteschlange abrufen Die Aufgabe an der Spitze der Warteschlange (mit der längsten Zeit in der Warteschlange) wird zur Ausführung in die Ereigniswarteschlange gestellt. Springt nach der Ausführung zu 3

Unter anderem wird die während der Ausführung des Codes hinzugefügte Mikrotask-Aufgabe im aktuellen Ereignisschleifenzeitraum ausgeführt und die neu hinzugefügte Eine Makrotask-Aufgabe kann nur warten, bis die nächste Ereignisschleife ausgeführt wird (eine Ereignisschleife führt nur eine Makrotask aus).
Schauen wir uns zunächst einen Code an.

console.log(1)
setTimeout(function() {
  //settimeout1
  console.log(2)
}, 0);
const intervalId = setInterval(function() {
  //setinterval1
  console.log(3)
}, 0)
setTimeout(function() {
  //settimeout2
  console.log(10)
  new Promise(function(resolve) {
    //promise1
    console.log(11)
    resolve()
  })
  .then(function() {
    console.log(12)
  })
  .then(function() {
    console.log(13)
    clearInterval(intervalId)
  })
}, 0);

//promise2
Promise.resolve()
  .then(function() {
    console.log(7)
  })
  .then(function() {
    console.log(8)
  })
console.log(9)
Nach dem Login kopieren

Was sollte Ihrer Meinung nach das Ergebnis sein? ?
Die Ergebnisse, die ich in der Knotenumgebung und der Chrome-Konsole ausgebe, sind wie folgt:

1
9
7
8
2
3
10
11
12
13
Nach dem Login kopieren

Im obigen Beispiel
die erste Ereignisschleife:

  1. console.log(1) wird ausgeführt, Ausgabe 1

  2. settimeout1 wird ausgeführt und zur Makrotask-Warteschlange hinzugefügt

  3. setinterval1 wird ausgeführt und zur Makrotask-Warteschlange hinzugefügt

  4. settimeout2 wird ausgeführt und zur Makrotask-Warteschlange hinzugefügt

  5. promise2 wird ausgeführt und seine zwei Die Funktion then wird zur Mikrotask-Warteschlange hinzugefügt

  6. console.log(9) wird ausgeführt und die Ausgabe ist 9

  7. Gemäß Die Definition der Ereignisschleife wird als nächstes ausgeführt. Die hinzugefügten Mikrotask-Aufgaben werden in der Reihenfolge ihres Eintritts in die Warteschlange ausgeführt. Console.log(7) und console.log(8) werden ausgegeben Die Warteschlange ist leer. Gehen Sie zurück zum ersten Schritt und betreten Sie die nächste Ereignisschleife. Zu diesem Zeitpunkt lautet die Makrotask-Warteschlange: settimeout1, setinterval1, settimeout2

Die zweite Ereignisschleife :

  1. aus der Makrotask-Warteschlange Holen Sie sich die Aufgabe an der Spitze des Teams (settimeout1) und führen Sie sie aus.

    Die Mikrotask-Warteschlange ist leer Der erste Schritt und die nächste Ereignisschleife. Zu diesem Zeitpunkt lautet die Makrotask-Warteschlange: setinterval1, settimeout2

Die dritte Ereignisschleife:

  1. Nehmen Sie die Aufgabe an der Spitze des Teams (setinterval1) aus der Makrotask-Warteschlange und führen Sie sie aus, geben Sie 3 aus und fügen Sie dann das neu generierte setinterval1 zur Makrotask-Warteschlange hinzu

    Die Mikrotask-Warteschlange ist leer. Kehren Sie zum ersten Schritt zurück und betreten Sie die nächste Ereignisschleife. Zu diesem Zeitpunkt lautet die Makrotask-Warteschlange: settimeout2, setinterval1

Die vierte Ereignisschleife:

  1. Nehmen Sie die Aufgabe an der Spitze des Teams (settimeout2) aus der Makrotask-Warteschlange, führen Sie sie aus, geben Sie 10 aus und führen Sie die Funktion in New Promise aus (Die Funktion in New Promise ist eine synchrone Operation. keine asynchrone Operation), geben Sie 11 aus und fügen Sie die beiden Then-Funktionen zur Mikrotask-Warteschlange hinzu

  2. Nehmen Sie aus der Mikrotask-Warteschlange die Aufgabe an der Spitze der Warteschlange und führen Sie sie aus, bis sie leer ist. Daher werden die beiden neu hinzugefügten Mikrotask-Aufgaben nacheinander ausgeführt, 12 und 13 ausgegeben und setinterval1 gelöscht.
    Zu diesem Zeitpunkt sind sowohl die Mikrotask-Warteschlange als auch die Makrotask-Warteschlange leer, und der Browser prüft immer, ob die Warteschlange leer ist leer und auf neue warten Die Aufgabe wird zur Warteschlange hinzugefügt.

Hier fragen Sie sich vielleicht, warum in der ersten Schleife die Makroaufgabe nicht zuerst ausgeführt wird? Denn sollten wir je nach Prozess nicht zuerst prüfen, ob die Makrotask-Warteschlange leer ist, und dann die Mikrotask-Warteschlange überprüfen?
Grund: Da es sich bei der Aufgabe, die zu Beginn im js-Hauptthread ausgeführt wird, um eine Makrotask-Aufgabe handelt, wird gemäß dem Prozess der Ereignisschleife nur eine Makrotask-Aufgabe in einer Ereignisschleife ausgeführt Im Hauptthread wird die erste Aufgabe aus der Mikrotask-Warteschlange entnommen und ausgeführt.

Hinweis:

Wenn eine Mikrotask-Aufgabe ausgeführt wird, tritt sie nur dann in die nächste Ereignisschleife ein, wenn die Mikrotask-Warteschlange leer ist Mikrotask-Aufgaben führen dazu, dass der Hauptthread Mikrotask-Aufgaben ausführt, und es gibt keine Möglichkeit, Makrotask-Aufgaben auszuführen. Auf diese Weise können wir keine UI-Rendering-/IO-Operationen/Ajax-Anfragen ausführen . geschehen. In „process.nexttick“ in nodejs können Sie die maximale Anzahl von Aufrufen festlegen, um ein Blockieren des Hauptthreads zu verhindern.

Damit führen wir ein neues Problem ein, das Timer-Problem. Ist der Timer echt und zuverlässig? Wenn ich beispielsweise einen Befehl ausführe: setTimeout(task, 100), wird er dann genau nach 100 Millisekunden ausgeführt? Tatsächlich können wir aufgrund der obigen Diskussion wissen, dass dies unmöglich ist.
Ich denke, jeder sollte den Grund kennen, denn nachdem Sie setTimeout(task,100) ausgeführt haben, stellen Sie eigentlich nur sicher, dass die Aufgabe nach 100 Millisekunden in die Makrotask-Warteschlange gelangt, aber das bedeutet vielleicht nicht, dass sie sofort ausgeführt werden kann Der Hauptthread führt derzeit einen zeitaufwändigen Vorgang aus, oder es befinden sich möglicherweise viele Aufgaben in der Mikrotask-Warteschlange. Dies kann der Grund sein, warum alle setTimeout kritisiert haben.

Das Obige ist nur meine persönliche Meinung der Event-Schleife. Einige Meinungen und Referenzen aus anderen hervorragenden Artikeln

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung von Beispielen für die js-Ereignisschleife. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
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

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Beste grafische Einstellungen
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. So reparieren Sie Audio, wenn Sie niemanden hören können
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Wie man alles in Myrise freischaltet
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Einfaches JavaScript-Tutorial: So erhalten Sie den HTTP-Statuscode Einfaches JavaScript-Tutorial: So erhalten Sie den HTTP-Statuscode Jan 05, 2024 pm 06:08 PM

JavaScript-Tutorial: So erhalten Sie HTTP-Statuscode. Es sind spezifische Codebeispiele erforderlich. Vorwort: Bei der Webentwicklung ist häufig die Dateninteraktion mit dem Server erforderlich. Bei der Kommunikation mit dem Server müssen wir häufig den zurückgegebenen HTTP-Statuscode abrufen, um festzustellen, ob der Vorgang erfolgreich ist, und die entsprechende Verarbeitung basierend auf verschiedenen Statuscodes durchführen. In diesem Artikel erfahren Sie, wie Sie mit JavaScript HTTP-Statuscodes abrufen und einige praktische Codebeispiele bereitstellen. Verwenden von XMLHttpRequest

Der Lambda-Ausdruck bricht aus der Schleife aus Der Lambda-Ausdruck bricht aus der Schleife aus Feb 20, 2024 am 08:47 AM

Wenn der Lambda-Ausdruck aus der Schleife ausbricht, sind spezifische Codebeispiele erforderlich. Bei der Programmierung ist die Schleifenstruktur eine wichtige Syntax, die häufig verwendet wird. Unter bestimmten Umständen möchten wir jedoch möglicherweise aus der gesamten Schleife ausbrechen, wenn eine bestimmte Bedingung im Schleifenkörper erfüllt ist, anstatt nur die aktuelle Schleifeniteration zu beenden. Zu diesem Zeitpunkt können uns die Eigenschaften von Lambda-Ausdrücken dabei helfen, das Ziel zu erreichen, aus der Schleife zu springen. Der Lambda-Ausdruck ist eine Möglichkeit, eine anonyme Funktion zu deklarieren, die intern einfache Funktionslogik definieren kann. Es unterscheidet sich von einer gewöhnlichen Funktionsdeklaration:

So implementieren Sie die Änderungsereignisbindung ausgewählter Elemente in jQuery So implementieren Sie die Änderungsereignisbindung ausgewählter Elemente in jQuery Feb 23, 2024 pm 01:12 PM

jQuery ist eine beliebte JavaScript-Bibliothek, die zur Vereinfachung der DOM-Manipulation, Ereignisbehandlung, Animationseffekte usw. verwendet werden kann. Bei der Webentwicklung stoßen wir häufig auf Situationen, in denen wir die Ereignisbindung für ausgewählte Elemente ändern müssen. In diesem Artikel wird erläutert, wie Sie mit jQuery ausgewählte Elementänderungsereignisse binden, und es werden spezifische Codebeispiele bereitgestellt. Zuerst müssen wir ein Dropdown-Menü mit Optionen erstellen, die Beschriftungen verwenden:

So erhalten Sie auf einfache Weise HTTP-Statuscode in JavaScript So erhalten Sie auf einfache Weise HTTP-Statuscode in JavaScript Jan 05, 2024 pm 01:37 PM

Einführung in die Methode zum Abrufen des HTTP-Statuscodes in JavaScript: Bei der Front-End-Entwicklung müssen wir uns häufig mit der Interaktion mit der Back-End-Schnittstelle befassen, und der HTTP-Statuscode ist ein sehr wichtiger Teil davon. Das Verstehen und Abrufen von HTTP-Statuscodes hilft uns, die von der Schnittstelle zurückgegebenen Daten besser zu verarbeiten. In diesem Artikel wird erläutert, wie Sie mithilfe von JavaScript HTTP-Statuscodes erhalten, und es werden spezifische Codebeispiele bereitgestellt. 1. Was ist ein HTTP-Statuscode? HTTP-Statuscode bedeutet, dass der Dienst den Dienst anfordert, wenn er eine Anfrage an den Server initiiert

So erstellen Sie ereignisbasierte Anwendungen mit PHP So erstellen Sie ereignisbasierte Anwendungen mit PHP May 04, 2024 pm 02:24 PM

Zu den Methoden zum Erstellen ereignisbasierter Anwendungen in PHP gehört die Verwendung der EventSourceAPI zum Erstellen einer Ereignisquelle und die Verwendung des EventSource-Objekts zum Abhören von Ereignissen auf der Clientseite. Senden Sie Ereignisse mithilfe von Server Sent Events (SSE) und warten Sie auf der Clientseite mithilfe eines XMLHttpRequest-Objekts auf Ereignisse. Ein praktisches Beispiel ist die Verwendung von EventSource zur Aktualisierung der Bestandszahlen in Echtzeit auf einer E-Commerce-Website. Dies wird auf der Serverseite durch zufälliges Ändern des Bestands und Senden von Aktualisierungen erreicht, und der Client wartet über EventSource auf Bestandsaktualisierungen und zeigt diese an Echtzeit.

Java Iterator vs. Iterable: Ein Schritt zum Schreiben eleganten Codes Java Iterator vs. Iterable: Ein Schritt zum Schreiben eleganten Codes Feb 19, 2024 pm 02:54 PM

Iterator-Schnittstelle Die Iterator-Schnittstelle ist eine Schnittstelle zum Durchlaufen von Sammlungen. Es bietet mehrere Methoden, darunter hasNext(), next() und remove(). Die Methode hasNext() gibt einen booleschen Wert zurück, der angibt, ob es ein nächstes Element in der Sammlung gibt. Die Methode next() gibt das nächste Element in der Sammlung zurück und entfernt es aus der Sammlung. Die Methode „remove()“ entfernt das aktuelle Element aus der Sammlung. Das folgende Codebeispiel zeigt, wie die Iterator-Schnittstelle zum Durchlaufen einer Sammlung verwendet wird: Listnames=Arrays.asList("John","Mary","Bob");Iterator

Welche Alternativen gibt es zu rekursiven Aufrufen in Java-Funktionen? Welche Alternativen gibt es zu rekursiven Aufrufen in Java-Funktionen? May 05, 2024 am 10:42 AM

Ersetzen rekursiver Aufrufe in Java-Funktionen durch Iteration. In Java ist die Rekursion ein leistungsstarkes Werkzeug zur Lösung verschiedener Probleme. In einigen Fällen kann die Verwendung von Iteration jedoch eine bessere Option sein, da sie effizienter und weniger anfällig für Stapelüberläufe ist. Hier sind die Vorteile der Iteration: Effizienter, da nicht für jeden rekursiven Aufruf ein neuer Stapelrahmen erstellt werden muss. Es ist weniger wahrscheinlich, dass Stapelüberläufe auftreten, da die Stapelplatznutzung begrenzt ist. Iterative Methoden als Alternative zu rekursiven Aufrufen: In Java gibt es mehrere Methoden, um rekursive Funktionen in iterative Funktionen umzuwandeln. 1. Verwenden Sie den Stapel. Die Verwendung des Stapels ist die einfachste Möglichkeit, eine rekursive Funktion in eine iterative Funktion umzuwandeln. Der Stapel ist eine Last-In-First-Out-Datenstruktur (LIFO), ähnlich einem Funktionsaufrufstapel. publicintfa

PHP gibt alle Werte im Array zurück, um ein Array zu bilden PHP gibt alle Werte im Array zurück, um ein Array zu bilden Mar 21, 2024 am 09:06 AM

In diesem Artikel wird ausführlich erläutert, wie PHP alle Werte eines Arrays zurückgibt, um ein Array zu bilden. Der Herausgeber hält dies für recht praktisch, daher teile ich es Ihnen als Referenz mit und hoffe, dass Sie nach dem Lesen dieses Artikels etwas gewinnen können . Verwenden der Funktion array_values() Die Funktion array_values() gibt ein Array aller Werte in einem Array zurück. Die Schlüssel des ursprünglichen Arrays bleiben nicht erhalten. $array=["foo"=>"bar","baz"=>"qux"];$values=array_values($array);//$values ​​​​werden ["bar","qux"]Verwendet Eine Schleife kann eine Schleife verwenden, um alle Werte des Arrays manuell abzurufen und zu einem neuen hinzuzufügen

See all articles