Haben Sie sich jemals gefragt, warum einige Teile des JavaScript-Codes scheinbar nicht in der richtigen Reihenfolge sind? Der Schlüssel zum Verständnis ist die Ereignisschleife.
Die Ereignisschleife von JavaScript kann schwierig zu verstehen sein, insbesondere wenn es um verschiedene Arten asynchroner Vorgänge geht. In diesem Artikel erklären wir, wie JavaScript mit synchronem und asynchronem Code, Mikrotasks und Makrotasks umgeht und warum bestimmte Dinge passieren in einer bestimmten Reihenfolge.
JavaScript verarbeitet Vorgänge im Wesentlichen auf zwei Arten: synchron und asynchron. Das Verständnis der Unterschiede zwischen ihnen ist der Schlüssel zum Verständnis, wie JavaScript Aufgaben erledigt und wie man effizienten und nicht blockierenden Code schreibt.
Synchroner Code ist die Standardeinstellung in JavaScript, was bedeutet, dass jede Zeile nacheinander ausgeführt wird. Zum Beispiel:
console.log("First"); console.log("Second");
Dies wird Folgendes ausgeben:
First Second
Asynchroner Code hingegen ermöglicht es, dass bestimmte Aufgaben im Hintergrund ausgeführt und später abgeschlossen werden, ohne den Rest des Codes zu blockieren. Funktionen wie setTimeout() oder Promise sind Beispiele für asynchronen Code.
Hier ist ein einfaches Beispiel für asynchronen Code mit setTimeout():
console.log("First"); setTimeout(() => { console.log("Second"); }, 0); console.log("Third");
Dies wird Folgendes ausgeben:
First Third Second
Es gibt mehrere Möglichkeiten, asynchrone Vorgänge in JavaScript zu handhaben:
Codebeispiel:
console.log("Start"); function asyncTask(callback) { setTimeout(() => { console.log("Async task completed"); callback(); }, 2000); } asyncTask(() => { console.log("Task finished"); }); console.log("End");
Codebeispiel:
console.log("Start"); const asyncTask = new Promise((resolve) => { setTimeout(() => { console.log("Async task completed"); resolve(); }, 2000); }); asyncTask.then(() => { console.log("Task finished"); }); console.log("End");
Codebeispiel:
console.log("Start"); async function asyncTask() { await new Promise((resolve) => { setTimeout(() => { console.log("Async task completed"); resolve(); }, 2000); }); console.log("Task finished"); } asyncTask(); console.log("End");
Um jede dieser Methoden zur Ausführung von Javascript besser zu verstehen und zu verstehen, wie sie sich voneinander unterscheiden, finden Sie hier eine ausführliche Beschreibung der Unterschiede in mehreren Aspekten von Javascript-Funktionen.
Aspect | Synchronous Code | Asynchronous Code |
---|---|---|
Execution Order | Executes line by line in a sequential manner | Allows tasks to run in the background while other code continues to execute |
Performance | Can lead to performance issues if long-running tasks are involved | Better performance for I/O-bound operations; prevents UI freezing in browser environments |
Code Complexity | Generally simpler and easier to read | Can be more complex, especially with nested callbacks (callback hell) |
Memory Usage | May use more memory if waiting for long operations | Generally more memory-efficient for long-running tasks |
Scalability | Less scalable for applications with many concurrent operations | More scalable, especially for applications handling multiple simultaneous operations |
This comparison highlights the key differences between synchronous and asynchronous code, helping developers choose the appropriate approach based on their specific use case and performance requirements.
In JavaScript, microtasks and macrotasks are two types of tasks that are queued and executed in different parts of the event loop, which determines how JavaScript handles asynchronous operations.
Microtasks and macrotasks are both queued and executed in the event loop, but they have different priorities and execution contexts. Microtasks are processed continuously until the microtask queue is empty before moving on to the next task in the macrotask queue. Macrotasks, on the other hand, are executed after the microtask queue has been emptied and before the next event loop cycle starts.
Microtasks are tasks that need to be executed after the current operation completes but before the next event loop cycle starts. Microtasks get priority over macrotasks and are processed continuously until the microtask queue is empty before moving on to the next task in the macrotask queue.
console.log("Start"); Promise.resolve().then(() => { console.log("Microtask"); }); console.log("End");
Start End Microtask
Macrotasks are tasks that are executed after the microtask queue has been emptied and before the next event loop cycle starts. These tasks represent operations like I/O or rendering and are usually scheduled after a certain event or after a delay.
console.log("Start"); setTimeout(() => { console.log("Macrotask"); }, 0); console.log("End");
Start End Macrotask
Aspect | Microtasks | Macrotasks |
---|---|---|
Execution Timing | Executed immediately after the current script, before rendering | Executed in the next event loop iteration |
Queue Priority | Higher priority, processed before macrotasks | Lower priority, processed after all microtasks are complete |
Examples | Promises, queueMicrotask(), MutationObserver | setTimeout(), setInterval(), I/O operations, UI rendering |
Use Case | For tasks that need to be executed as soon as possible without yielding to the event loop | For tasks that can be deferred or don't require immediate execution |
Die Ereignisschleife ist ein grundlegendes Konzept in JavaScript, das nicht blockierende asynchrone Vorgänge ermöglicht, obwohl JavaScript Single-Threaded ist. Es ist für die Verarbeitung asynchroner Rückrufe verantwortlich und stellt sicher, dass JavaScript weiterhin reibungslos läuft, ohne durch zeitaufwändige Vorgänge blockiert zu werden.
Die Ereignisschleife ist ein Mechanismus, der es JavaScript ermöglicht, asynchrone Vorgänge effizient abzuwickeln. Es überprüft kontinuierlich den Aufrufstapel und die Task-Warteschlange (oder Mikrotask-Warteschlange), um zu bestimmen, welche Funktion als nächstes ausgeführt werden soll.
Um die Ereignisschleife besser zu verstehen, ist es wichtig zu wissen, wie JavaScript intern funktioniert. Es ist wichtig zu beachten, dass JavaScript eine Single-Threaded-Sprache ist, was bedeutet, dass sie jeweils nur eine Sache ausführen kann. Es gibt nur einen Aufrufstapel, der die auszuführenden Funktionen speichert. Dies macht synchronen Code unkompliziert, stellt jedoch ein Problem für Aufgaben wie das Abrufen von Daten von einem Server oder das Festlegen eines Timeouts dar, deren Ausführung einige Zeit in Anspruch nimmt. Ohne die Ereignisschleife würde JavaScript auf diese Aufgaben warten und nichts anderes würde passieren.
Im Aufrufstapel wird die aktuell ausgeführte Funktion gespeichert. JavaScript fügt während der Codeverarbeitung Funktionen zur Aufrufliste hinzu und entfernt sie daraus.
Wenn eine asynchrone Aufgabe wie setTimeout, fetch oder Promise auftritt, delegiert JavaScript diese Aufgabe an die Web-APIs des Browsers (wie Timer-API, Netzwerk-API usw.), die die Aufgabe im Hintergrund verarbeiten.
Sobald die asynchrone Aufgabe abgeschlossen ist (z. B. der Timer abgelaufen ist oder Daten vom Server empfangen wurden), wird der Rückruf (die Funktion zur Verarbeitung des Ergebnisses) in die Aufgabenwarteschlange (oder Mikrotask-Warteschlange im Fall von Versprechen) verschoben. .
JavaScript führt weiterhin den synchronen Code aus. Sobald der Aufrufstapel leer ist, holt die Ereignisschleife die erste Aufgabe aus der Aufgabenwarteschlange (oder Mikrotaskwarteschlange) und platziert sie zur Ausführung auf dem Aufrufstapel.
Dieser Vorgang wiederholt sich. Die Ereignisschleife stellt sicher, dass alle asynchronen Aufgaben bearbeitet werden, nachdem die aktuellen synchronen Aufgaben erledigt sind.
Da wir nun besser und klarer verstehen, wie die Ereignisschleife funktioniert, schauen wir uns einige Beispiele an, um unser Verständnis zu festigen.
function exampleOne() { console.log("Start"); setTimeout(() => { console.log("Timeout done"); }, 1000); Promise.resolve().then(() => { console.log("Resolved"); }); console.log("End"); } exampleOne();
Start End Resolved Timeout done
function exampleTwo() { console.log("Start"); setTimeout(() => { console.log("Timer 1"); }, 0); Promise.resolve().then(() => { console.log("Promise 1 Resolved"); setTimeout(() => { console.log("Timer 2"); }, 0); return Promise.resolve().then(() => { console.log("Promise 2 Resolved"); }); }); console.log("End"); } exampleTwo();
Start End Promise 1 Resolved Promise 2 Resolved Timer 1 Timer 2
function exampleThree() { console.log("Step 1: Synchronous"); setTimeout(() => { console.log("Step 2: Timeout 1"); }, 0); Promise.resolve().then(() => { console.log("Step 3: Promise 1 Resolved"); Promise.resolve().then(() => { console.log("Step 4: Promise 2 Resolved"); }); setTimeout(() => { console.log("Step 5: Timeout 2"); }, 0); }); setTimeout(() => { console.log( "Step 6: Immediate (using setTimeout with 0 delay as fallback)" ); }, 0); console.log("Step 7: Synchronous End"); } exampleThree();
Step 1: Synchronous Step 7: Synchronous End Step 3: Promise 1 Resolved Step 4: Promise 2 Resolved Step 2: Timeout 1 Step 6: Immediate (using setTimeout with 0 delay as fallback) Step 5: Timeout 2
In JavaScript, mastering synchronous and asynchronous operations, as well as understanding the event loop and how it handles tasks, is crucial for writing efficient and performant applications.
The examples provided progressively illustrated the interaction between synchronous code, promises, timers, and the event loop. Understanding these concepts is key to mastering asynchronous programming in JavaScript, ensuring your code runs efficiently and avoids common pitfalls such as race conditions or unexpected execution orders.
To ensure you don't miss any part of this series and to connect with me for more in-depth discussions on Software Development (Web, Server, Mobile or Scraping / Automation), push notifications, and other exciting tech topics, follow me on:
Stay tuned and happy coding ???
Das obige ist der detaillierte Inhalt vonAsynchrone Programmierung in JavaScript verstehen: Einsteigerleitfaden zur Ereignisschleife. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!