
So können Sie schnell mit VUE3.0 beginnen: Erfahren Sie mehr
über den Ausführungskontext, den Ausführungsstapel und den Ausführungsmechanismus (synchrone Aufgaben, asynchrone Aufgaben, Mikrotasks, Makrotasks und Ereignisschleifen) in js Dies ist ein häufiger Testpunkt in Interviews Einige Freunde sind möglicherweise verwirrt, wenn Sie gefragt werden. Deshalb werde ich es heute zusammenfassen und hoffe, dass es Ihnen vor dem Bildschirm hilfreich sein kann.
Bevor wir über den Ausführungskontext und js -Ausführungsmechanismus in js sprechen, sprechen wir über Threads und Prozesse.
In offiziellen Begriffen ist线程die kleinste Einheit der CPU Planung.
? Offiziell ist进程die kleinste Einheit der CPU Ressourcenzuweisung.
线程ist eine Programmlaufeinheit, die auf进程basiert. Laienhaft ausgedrückt ist线程ein Ausführungsablauf in einem Programm. Ein进程kann einen oder mehrere线程haben.
Es gibt nur einen Ausführungsfluss in einem进程, der单线程bezeichnet wird. Das heißt, wenn das Programm ausgeführt wird, werden die verwendeten Programmpfade in aufeinanderfolgender Reihenfolge angeordnet. Die vorherigen müssen verarbeitet werden, bevor die späteren ausgeführt werden.
Mehrere Ausführungsströme in einem进程werden als多线程bezeichnet. Das heißt, mehrere verschiedene线程können gleichzeitig in einem Programm ausgeführt werden, um unterschiedliche Aufgaben auszuführen. Dies bedeutet, dass ein einzelnes Programm mehrere parallele线程erstellen darf, um ihre jeweiligen Aufgaben auszuführen. .
Der Autor gibt unten ein einfaches Beispiel: Wenn wir qq音乐öffnen und Lieder anhören, können wir qq音乐als einen Prozess verstehen qq音乐wir herunterladen können Zu Liedern ist ein Thread, und das Herunterladen ist ein Prozess. Wenn wir vscode erneut öffnen, um Code zu schreiben, ist dies ein weiterer Vorgang.
Prozesse sind unabhängig voneinander, einige Ressourcen werden jedoch von Threads unter demselben Prozess gemeinsam genutzt.
Der Lebenszyklus eines Threads durchläuft fünf Phasen.
Neuer Status: Nachdem das Schlüsselwort new und Thread -Klasse oder ihre Unterklasse zum Erstellen eines Thread-Objekts verwendet wurden, befindet sich das Thread-Objekt im neuen Status. Es bleibt in diesem Zustand, bis das Programm den Thread start() .
Bereitzustand: Wenn das Thread-Objekt start() aufruft, wechselt der Thread in den Bereitschaftszustand. Der Thread im Bereitschaftszustand befindet sich in der Bereitschaftswarteschlange und kann sofort ausgeführt werden, sofern er das Recht zur Nutzung CPU erhält.
Ausführungsstatus: Wenn der Thread im Bereitschaftsstatus CPU Ressourcen erhält, kann er run() ausführen und der Thread befindet sich im Ausführungsstatus. Der Thread im laufenden Zustand ist am komplexesten, er kann blockiert, bereit und tot werden.
Blockierungsstatus: Wenn ein Thread die Methoden sleep(睡眠) , suspend(挂起) , wait(等待) und andere ausführt, wechselt der Thread nach dem Verlust der belegten Ressourcen aus dem laufenden Status in den Blockierungsstatus. Der Bereitschaftszustand kann wieder aktiviert werden, nachdem die Ruhezeit abgelaufen ist oder Geräteressourcen abgerufen wurden. Es kann in drei Typen unterteilt werden:
Warteblockierung: Der Thread im laufenden Zustand führt wait() aus, wodurch der Thread in den Warteblockierungsstatus wechselt.
Synchronblockierung: Der Thread kann die synchronized Synchronisationssperre nicht erhalten (da die Synchronisationssperre von anderen Threads belegt ist).
Andere Blockierung: Wenn I/O Anfrage durch den Aufruf von sleep() oder join() des Threads ausgegeben wird, wechselt der Thread in den Blockierungszustand. Wenn sleep() abläuft, wartet join() auf die Beendigung oder Zeitüberschreitung des Threads oder auf den Abschluss der I/O -Verarbeitung und der Thread kehrt in den Bereitschaftszustand zurück.
Todeszustand: Wenn ein laufender Thread seine Aufgabe abschließt oder andere Beendigungsbedingungen auftreten, wechselt der Thread in den beendeten Zustand.

JS ist Single-Threaded. Als Browser-Skriptsprache wird JS hauptsächlich zur Interaktion mit Benutzern und zur Bedienung DOM verwendet. Dies legt fest, dass es nur Single-Threaded sein kann, da es sonst zu sehr komplexen Synchronisationsproblemen kommt. Angenommen, JavaScript verfügt über zwei Threads gleichzeitig. Ein Thread fügt Inhalt zu einem bestimmten DOM Knoten hinzu und der andere Thread löscht den Knoten. Welchen Thread sollte der Browser in diesem Fall verwenden?
Wenn JS Engine ein ausführbares Codefragment analysiert (normalerweise die Funktionsaufrufphase), führt sie vor der Ausführung zunächst einige vorbereitende Arbeiten durch. (Ausführungskontext (als EC bezeichnet)“ oder kann auch als Ausführungsumgebung bezeichnet werden.
Es gibt drei Ausführungskontexttypen in javascript :
Globaler Ausführungskontext . Dies ist der Standard- oder grundlegendste Ausführungskontext. Es gibt nur einen globalen Kontext in einem Programm, der während des gesamten Lebenszyklus vorhanden ist javascript Skript. Der untere Teil des Ausführungsstapels wird durch das Stapeln nicht zerstört. Der globale Kontext generiert ein globales Objekt (am Beispiel der Browserumgebung ist dieses globale Objekt window ) und bindet this Wert an dieses globale Objekt.
Funktionsausführungskontext Bei jedem Aufruf einer Funktion wird ein neuer Funktionsausführungskontext erstellt (unabhängig davon, ob die Funktion wiederholt aufgerufen wird).
Ausführungskontext der Eval-Funktion Der in eval Funktion ausgeführte Code verfügt ebenfalls über einen eigenen Ausführungskontext. Da eval jedoch nicht häufig verwendet wird, wird er hier nicht analysiert.
Wir haben bereits erwähnt, dass js beim Ausführen einen Ausführungskontext erstellt, der Ausführungskontext jedoch gespeichert werden muss. Womit wird er also gespeichert? Sie müssen die Stapeldatenstruktur verwenden.
Der Stapel ist eine First-In-Last-Out-Datenstruktur.

Zusammenfassend ist der Ausführungskontext, der zum Speichern des beim Ausführen des Codes erstellten Ausführungskontexts verwendet wird, der Ausführungsstapel .
Beim Ausführen eines Codeabschnitts JS
Anschließend erstellt JS Engine einen globalen Ausführungskontext und push auf den Ausführungsstapel. In diesem Prozess weist JS Engine allen Variablen in diesem Code einen Anfangswert zu (undefiniert). Die JS Engine tritt in die Ausführungsphase ein. In diesem Prozess führt JS Engine den Code Zeile für Zeile aus, dh weist den Variablen, denen Speicher zugewiesen wurde, nacheinander Werte (reale Werte) zu.
Wenn in diesem Code function vorhanden ist, erstellt JS Engine einen Funktionsausführungskontext und push auf den Ausführungsstapel. Der Erstellungs- und Ausführungsprozess ist der gleiche wie der globale Ausführungskontext.
Wenn ein Ausführungsstapel abgeschlossen ist, wird der Ausführungskontext vom Stapel entfernt und dann wird der nächste Ausführungskontext eingegeben.
Lassen Sie mich unten ein Beispiel geben. Wenn wir den folgenden Code in unserem Programm haben:
console.log("Global Execution Context start");
Funktion first() {
console.log("erste Funktion");
zweite();
console.log("Wieder erste Funktion");
}
Funktion second() {
console.log("zweite Funktion");
}
Erste();
console.log("Global Execution Context end"); Lassen Sie uns das obige Beispiel kurz analysieren.
Zuerst wird ein Ausführungsstapel erstellt
, dann wird ein globaler Kontext erstellt und der Ausführungskontext wird auf den Ausführungsstapel push ,
um die Ausführung zu starten , und Global Execution Context start
trifft auf first Methode, führt die Methode aus, erstellt einen Funktionsausführungskontext und push auf den Ausführungsstapel,
um first Ausführungskontext auszuführen, gibt die first function aus,
trifft auf second Methode und führt die Methode aus , erstellt einen Funktionsausführungskontext und push auf den Ausführungsstapel, um
second Ausführungskontext auszuführen, die zweite second function
second ausgeführt, vom Stapel entfernt und in den nächsten Ausführungskontext eingegeben first
first Ausführungskontext wird fortgesetzt Ausführung, Ausgabe Again first function
wurde die erste Funktion ausgeführt, vom Stapel entfernt und in den nächsten Ausführungskontext eingegeben. first Ausführungskontext.
Globaler Ausführungskontext. Ausführung und Ausgabe fortsetzen. Global Execution Context end
Wir verwenden ein Bild zur Zusammenfassung

In Ordnung. Nachdem wir über den Ausführungskontext und den Ausführungsstapel gesprochen haben, sprechen wir über den Ausführungsmechanismus von js. Wenn wir über den Ausführungsmechanismus von js sprechen
müssen js die synchronen Aufgaben, asynchronen Aufgaben, Makroaufgaben und Mikroaufgaben in js verstehen.
In js werden Aufgaben in synchrone Aufgaben und asynchrone Aufgaben unterteilt. Was sind also synchrone Aufgaben und was sind asynchrone Aufgaben?
Synchrone Aufgaben beziehen sich auf Aufgaben, die zur Ausführung im Hauptthread in die Warteschlange gestellt werden. Die nächste Aufgabe kann erst ausgeführt werden, nachdem die vorherige Aufgabe ausgeführt wurde.
Asynchrone Aufgaben beziehen sich auf Aufgaben, die nicht in den Hauptthread, sondern in die „Aufgabenwarteschlange“ gelangen (Aufgaben in der Aufgabenwarteschlange werden nur dann parallel zum Hauptthread ausgeführt, wenn der Hauptthread inaktiv ist und die „Aufgabenwarteschlange“ benachrichtigt wird). Hauptthread, eine asynchrone Aufgabe Sobald sie ausgeführt werden kann, wird die Aufgabe zur Ausführung in den Hauptthread eingegeben. Da es sich um einen Warteschlangenspeicher handelt, erfüllt er die First-In-First-Out-Regel . Zu den gängigen asynchronen Aufgaben gehören setInterval , setTimeout , promise.then usw.
hat zuvor synchrone Aufgaben und asynchrone Aufgaben eingeführt. Lassen Sie uns nun über die Ereignisschleife sprechen.
Synchrone und asynchrone Aufgaben gelangen jeweils an unterschiedliche Ausführungsorte und gelangen synchron in den Hauptthread. Erst wenn die vorherige Aufgabe abgeschlossen ist, kann die nächste Aufgabe ausgeführt werden. Asynchrone Aufgaben gelangen nicht in den Hauptthread, sondern in Event Table und registrieren Funktionen.
Wenn die angegebene Sache abgeschlossen ist, verschiebt Event Table diese Funktion in Event Queue . Event Queue ist eine Warteschlangendatenstruktur und erfüllt daher die First-In-First-Out-Regel.
Wenn die Aufgaben im Hauptthread nach der Ausführung leer sind, wird die entsprechende Funktion aus Event Queue gelesen und im Hauptthread ausgeführt.
Der obige Vorgang wird kontinuierlich wiederholt, was oft als Ereignisschleife bezeichnet wird.
Fassen wir es mit einem Bild zusammen

Lassen Sie mich kurz eine Beispielfunktion
test1() { vorstellen
console.log("log1");
setTimeout(() => {
console.log("setTimeout 1000");
}, 1000);
setTimeout(() => {
console.log("setTimeout 100");
}, 100);
console.log("log2");
}
test1(); // log1, log2, setTimeout 100, setTimeout 1000 Wir wissen, dass in js synchrone Aufgaben zuerst vor asynchronen Aufgaben ausgeführt werden, daher werden im obigen Beispiel zuerst log1、log2 ausgegeben
und dann asynchrone Aufgaben nach den synchronen ausgeführt
1000 setTimeout 1000
die Rückruffunktion mit einer Verzögerung von 100 Millisekunden zuerst die Ausgabe setTimeout 100 aus.
Das obige Beispiel ist meiner Meinung nach relativ einfach Solange Sie die vom Autor oben erwähnten synchronen und asynchronen Aufgaben verstehen, wird es kein Problem geben. Dann möchte ich Ihnen noch ein Beispiel geben, Freunde, mal sehen, wie das Ergebnis aussehen wird.
Funktion test2() {
console.log("log1");
setTimeout(() => {
console.log("setTimeout 1000");
}, 1000);
setTimeout(() => {
console.log("setTimeout 100");
}, 100);
neues Versprechen((auflösen, ablehnen) => {
console.log("neues Versprechen");
lösen();
}).then(() => {
console.log("promise.then");
});
console.log("log2");
}
test2(); Um das obige Problem zu lösen, reicht es nicht aus, synchrone und asynchrone Aufgaben zu kennen. Wir müssen auch Makroaufgaben und Mikroaufgaben kennen.
In js werden Aufgaben in zwei Typen unterteilt, einer heißt Makroaufgabe MacroTask und der andere heißt Mikroaufgabe MicroTask .
Die gemeinsame Makroaufgabe MacroTask hat
den Hauptcodeblock
setTimeout()
setInterval()
setImmediate() - Knoten
requestAnimationFrame() -
Der gemeinsame Mikroaufgabe MicroTask hat
Promise.then()
Process.nextTick() -
Knoten obiges Beispiel Es handelt sich um Makroaufgaben und Mikroaufgaben. Wie ist die Ausführungsreihenfolge von Makroaufgaben und Mikroaufgaben?
Wenn das gesamte script (als erste Makroaufgabe) ausgeführt wird, wird zunächst der gesamte Code in zwei Teile unterteilt: synchrone Aufgaben und asynchrone Aufgaben. Die synchronen Aufgaben werden direkt in den Hauptthread eingegeben und nacheinander ausgeführt. und die asynchronen Aufgaben werden in die asynchrone Warteschlange eingegeben und dann in Makroaufgaben und Mikroaufgaben unterteilt.
Die Makroaufgabe tritt in Event Table ein und registriert darin eine Rückruffunktion. Immer wenn das angegebene Ereignis abgeschlossen ist, verschiebt Event Table diese Event Queue
in die Event Table Sobald das angegebene Ereignis abgeschlossen ist, verschiebt Event Table diese Funktion in Event Queue
Event Queue die Aufgaben im Hauptthread abgeschlossen sind und der Hauptthread leer ist, wird überprüft, ob Aufgaben vorhanden sind , alle Ausführen, wenn nicht, führen Sie die nächste Makroaufgabe aus.
Wir verwenden ein Bild, um es zusammenzufassen.

Nachdem wir die obigen Beispiele für asynchrone Makroaufgaben und Mikroaufgaben verstanden haben, können wir leicht die Antwort erhalten.
Wir wissen, dass in js synchrone Aufgaben zuerst vor asynchronen Aufgaben ausgeführt werden, sodass im obigen Beispiel zuerst log1、new promise、log2 ausgegeben werden. Hierbei ist zu beachten, dass der Hauptcodeblock des neuen Versprechens synchronisiert wird.
Nachdem die Makroaufgabe ausgeführt wurde, werden alle von dieser Makroaufgabe generierten Mikroaufgaben ausgeführt, sodass promise.then ausgegeben
wird , eine weitere Makroaufgabe wird ausgeführt, die Rückruffunktion wird um 100 Millisekunden verzögert und priorisiert die Ausführung und gibt setTimeout 100 aus.
Diese Makroaufgabe generiert keine Mikroaufgaben, sodass keine Mikroaufgaben ausgeführt werden müssen,
um mit der Ausführung der nächsten Makroaufgabe fortzufahren Die Funktion mit einer Verzögerung von 1000 priorisiert die Ausführung und gibt setTimeout 1000
Nachdem die Methode test2 ausgeführt wurde, werden log1、new promise、log2、promise.then、setTimeout 100、setTimeout 1000 nacheinander
ausgegeben Es gibt unterschiedliche Meinungen darüber, ob
jszuerst mit Makroaufgaben und dann mit Mikroaufgaben oder mit Mikroaufgaben vor Makroaufgaben ausgeführt werden soll. Das Verständnis des Autors ist, dass, wenn der gesamtejsCodeblock als Makroaufgabe betrachtet wird, unserejsAusführungsreihenfolge zuerst die Makroaufgabe und dann die Mikroaufgabe ist.
Wie das Sprichwort sagt: Einmal üben ist besser als hundertmal zuschauen. Im Folgenden gebe ich Ihnen zwei Beispiele. Wenn Sie es richtig machen, beherrschen Sie die Kenntnisse über den Ausführungsmechanismus von js .
Beispiel 1
Funktion test3() {
console.log(1);
setTimeout(function () {
console.log(2);
neues Versprechen(Funktion (Auflösung) {
console.log(3);
lösen();
}).then(function () {
console.log(4);
});
console.log(5);
}, 1000);
neues Versprechen(Funktion (Auflösung) {
console.log(6);
lösen();
}).then(function () {
console.log(7);
setTimeout(function () {
console.log(8);
});
});
setTimeout(function () {
console.log(9);
neues Versprechen(Funktion (Auflösung) {
console.log(10);
lösen();
}).then(function () {
console.log(11);
});
}, 100);
console.log(12);
}
test3(); Lassen Sie es uns im Detail analysieren.
Zuerst wird der gesamte js Codeblock als Makroaufgabe ausgeführt und 1, 1、6、12 werden nacheinander ausgegeben.
Nachdem die gesamte Codeblock-Makroaufgabe ausgeführt wurde, werden eine Mikroaufgabe und zwei Makroaufgaben generiert, sodass die Makroaufgabenwarteschlange zwei Makroaufgaben und die Mikroaufgabenwarteschlange eine Mikroaufgabe enthält.
Nachdem die Makroaufgabe ausgeführt wurde, werden alle von dieser Makroaufgabe generierten Mikroaufgaben ausgeführt. Da es nur eine Mikrotask gibt, werden 7 ausgegeben. Diese Mikrotask hat eine weitere Makrotask hervorgebracht, sodass sich derzeit drei Makrotasks in der Makrotask-Warteschlange befinden.
Von den drei Makrotasks wird diejenige ohne festgelegte Verzögerung zuerst ausgeführt, sodass 8 ausgegeben wird. Diese Makrotask generiert keine Mikrotasks, sodass keine Mikrotasks ausgeführt werden müssen, und die nächste Makrotask wird weiterhin ausgeführt.
Verzögern Sie die Ausführung der Makrotask um 100 Millisekunden, geben Sie 9、10 aus und generieren Sie eine Mikrotask, sodass die Mikrotask-Warteschlange derzeit über eine Mikrotask verfügt.
Nachdem die Makrotask ausgeführt wurde, werden alle von der Makrotask generierten Mikrotasks ausgeführt Alle Mikrotasks in der Task-Warteschlange geben 11 aus.
Die Makrotask-Ausführung erfolgt 2、3、5 einer Verzögerung von 1000 Millisekunden. Daher verfügt die Mikrotask-Warteschlange derzeit über eine Mikrotask
. Die Makrotask wird ausgeführt, sodass alle Mikrotasks in der Mikrotask-Warteschlange ausgeführt werden und 4 ausgegeben werden
. Das obige Codebeispiel gibt also 1、6、12、7、8、9、10、11、2、3、5、4 , 12, 7, 8, 9, 10, 11 aus , 2, 3, 5, 4 nacheinander. Habt ihr es richtig gemacht?
Beispiel 2:
Wir modifizieren das obige Beispiel 1 leicht und führen async und await
asynchrone Funktion test4() { ein.
console.log(1);
setTimeout(function () {
console.log(2);
neues Versprechen(Funktion (Auflösung) {
console.log(3);
lösen();
}).then(function () {
console.log(4);
});
console.log(5);
}, 1000);
neues Versprechen(Funktion (Auflösung) {
console.log(6);
lösen();
}).then(function () {
console.log(7);
setTimeout(function () {
console.log(8);
});
});
const result = wait async1();
console.log(result);
setTimeout(function () {
console.log(9);
neues Versprechen(Funktion (Auflösung) {
console.log(10);
lösen();
}).then(function () {
console.log(11);
});
}, 100);
console.log(12);
}
asynchrone Funktion async1() {
console.log(13)
return Promise.resolve("Promise.resolve");
}
test4(); Was wird das obige Beispiel ausgeben? Hier können wir das Problem von async und await leicht lösen.
Wir wissen async und await tatsächlich Syntaxzucker für Promise sind. Hier müssen wir nur wissen, await äquivalent zu Promise.then ist. Daher können wir das obige Beispiel als folgenden Code verstehen:
Funktion test4() {
console.log(1);
setTimeout(function () {
console.log(2);
neues Versprechen(Funktion (Auflösung) {
console.log(3);
lösen();
}).then(function () {
console.log(4);
});
console.log(5);
}, 1000);
neues Versprechen(Funktion (Auflösung) {
console.log(6);
lösen();
}).then(function () {
console.log(7);
setTimeout(function () {
console.log(8);
});
});
neues Versprechen(Funktion (Auflösung) {
console.log(13);
return discover("Promise.resolve");
}).then((result) => {
console.log(result);
setTimeout(function () {
console.log(9);
neues Versprechen(Funktion (Auflösung) {
console.log(10);
lösen();
}).then(function () {
console.log(11);
});
}, 100);
console.log(12);
});
}
test4(); Können Sie das Ergebnis leicht erhalten, nachdem Sie den obigen Code gesehen haben?
Zunächst wird der gesamte js -Codeblock zunächst als Makroaufgabe ausgeführt und nacheinander 1、6、13 ausgegeben.
Nachdem die gesamte Codeblock-Makroaufgabe ausgeführt wurde, werden zwei Mikroaufgaben und eine Makroaufgabe generiert, sodass die Makroaufgabenwarteschlange eine Makroaufgabe und die Mikroaufgabenwarteschlange zwei Mikroaufgaben enthält.
Nachdem die Makroaufgabe ausgeführt wurde, werden alle von dieser Makroaufgabe generierten Mikroaufgaben ausgeführt. Es werden also 7、Promise.resolve、12 ausgegeben. Diese Mikrotask hat zwei weitere Makrotasks hervorgebracht, sodass die Makrotask-Warteschlange derzeit drei Makrotasks enthält.
Von den drei Makrotasks wird diejenige ohne festgelegte Verzögerung zuerst ausgeführt, sodass 8 ausgegeben wird. Diese Makrotask generiert keine Mikrotasks, sodass keine Mikrotasks ausgeführt werden müssen, und die nächste Makrotask wird weiterhin ausgeführt.
Verzögern Sie die Ausführung der Makrotask um 100 Millisekunden, geben Sie 9、10 aus und generieren Sie eine Mikrotask, sodass die Mikrotask-Warteschlange derzeit über eine Mikrotask verfügt.
Nachdem die Makrotask ausgeführt wurde, werden alle von der Makrotask generierten Mikrotasks ausgeführt Alle Mikrotasks in der Task-Warteschlange geben 11 aus.
Die Makrotask-Ausführung erfolgt 2、3、5 einer Verzögerung von 1000 Millisekunden. Daher verfügt die Mikrotask-Warteschlange derzeit über eine Mikrotask
. Die Makrotask wird ausgeführt. Alle generierten Mikrotasks führen alle Mikrotasks in der Mikrotask-Warteschlange aus und geben 4 aus.
Daher gibt das obige Codebeispiel 1, 6, 13, 7 1、6、13、7、Promise.resolve、12、8、9、10、11、2、3、5、4 aus 1、6、13、7、Promise.resolve、12、8、9、10、11、2、3、5、4 4, habt ihr es richtig gemacht?
Viele Freunde verstehen setTimeout(fn) nicht. Ist es nicht offensichtlich, dass die Verzögerungszeit nicht sofort ausgeführt werden sollte?
Wir können setTimeout(fn) als setTimeout(fn,0) verstehen, was eigentlich dasselbe bedeutet.
Wir wissen, dass js in synchrone Aufgaben und asynchrone Aufgaben unterteilt ist. setTimeout(fn) ist eine asynchrone Aufgabe. Auch wenn Sie hier keine Verzögerungszeit festlegen, wird sie in die asynchrone Warteschlange eingegeben und erst ausgeführt, wenn der Hauptthread vorhanden ist Leerlauf.
Der Autor wird es noch einmal erwähnen. Glauben Sie, dass die Verzögerungszeit, die wir nach setTimeout festlegen, js definitiv entsprechend unserer Verzögerungszeit ausgeführt wird? Die von uns festgelegte Zeit dient nur dazu, die Rückruffunktion auszuführen, aber ob der Hauptthread frei ist, ist eine andere Sache. Wir können ein einfaches Beispiel geben.
Funktion test5() {
setTimeout(function () {
console.log("setTimeout");
}, 100);
sei i = 0;
while (wahr) {
i++;
}
}
test5(); Gibt das obige Beispiel definitiv setTimeout nach 100 Millisekunden aus? Nein, da unser Hauptthread in eine Endlosschleife eingetreten ist und keine Zeit hat, asynchrone Warteschlangenaufgaben auszuführen.
GUI渲染wird hier erwähnt. Einige Freunde verstehen es möglicherweise nicht im Detail. Hier ist nur ein kurzes Verständnis.
Da sich JS引擎线程und GUI渲染线程gegenseitig ausschließen, startet der Browser GUI渲染线程nach dem Ausführungsergebnis einer宏任务und vor dem, damit宏任务und DOM任务ordnungsgemäß ablaufen können Ausführung der nächsten宏任务, Rendern der Seite.
Daher ist die Beziehung zwischen Makroaufgaben, Mikroaufgaben und GUI-Rendering wie folgt:
Makroaufgabe -> Mikroaufgabe -> GUI-Rendering -> Makroaufgabe -> ...
[Empfehlung für zugehörige Video-Tutorials: Web-Frontend]
Das Obige ist Eine ausführliche Analyse von JavaScript. Weitere Informationen zum Ausführungskontext und Ausführungsmechanismus finden Sie in anderen verwandten Artikeln auf der chinesischen PHP-Website!
