suchen
HeimWeb-Frontendjs-TutorialWie versteht man die Javascript-Ereignisschleife? (Bilder und Text)

Der Inhalt dieses Artikels befasst sich mit dem Verständnis der Javascript-Ereignisschleife. (Bilder und Text), es hat einen gewissen Referenzwert. Freunde in Not können sich darauf beziehen.

Stapel und Warteschlangen

Zugriff auf Daten im Computerspeicher. Die grundlegenden Datenstrukturen sind in Stapel und Warteschlangen unterteilt.

Stapel ist eine Last-In-First-Out-Datenstruktur, aber der „Heap“ ist eine andere komplexe Datenstruktur. Es sind zwei verschiedene Dinge. Das Merkmal des Stapels besteht darin, dass Operationen nur an einem Ende ausgeführt werden. Im Allgemeinen gibt es nur zwei Stapeloperationen: Push und Pop. Die ersten Daten, die auf den Stapel gelegt werden, sind immer die letzten, die ausgegeben werden.

Wie versteht man die Javascript-Ereignisschleife? (Bilder und Text)

Die Warteschlange ähnelt dem Stapel, es handelt sich jedoch um eine First-In-First-Out-Datenstruktur. Der Vorgang des Einfügens von Daten wird von einem aus ausgeführt Ende der Warteschlange und Der Löschvorgang befindet sich auf der anderen Seite.

Wie versteht man die Javascript-Ereignisschleife? (Bilder und Text)

Eine gängige Metapher ist, dass ein Stapel wie ein aufgerichteter Eimer ist. Die zuerst in den Stapel gelegten Daten werden am Boden des Eimers platziert Die Daten werden einzeln an der Öffnung des Eimers entnommen, sodass die Daten, die zuerst in den Stapel gelegt werden, immer auch die letzten sind, die entnommen werden. Die Warteschlange ist wie eine Wasserleitung. Die ersten Daten, die in die Warteschlange gestellt werden, fließen als erstes am anderen Ende der Warteschlange heraus.

In JavaScript ist die Ausführung einer Funktion ein typischer Prozess des Schiebens und Knallens des Stapels:

function fun1() {
    function fun2() {
        function fun3() {
            console.log('do it');
        }
        fun3();
    }
    fun2();
}
fun1();

Wenn das Programm ausgeführt wird, werden fun1, fun2 und fun3 zuerst auf den Stapel geschoben Nacheinander und dann Beim Aufruf einer Funktion wird zuerst fun3 aufgerufen (gepoppt), dann fun2 und fun1. Stellen Sie sich vor, wenn fun1 zuerst vom Stapel entfernt wird, gehen die Funktionen fun2 und fun3 verloren.

Single-Threaded und asynchron

In der Sprache von JavaScript ist das Programm Single-Threaded und hat nur einen Haupt-Thread. Weil es nicht schwer ist, sich vorzustellen, dass JavaScript ursprünglich als Skriptsprache konzipiert wurde, die im Browser ausgeführt wird. Wenn es für Multithreading ausgelegt ist und zwei Threads gleichzeitig das DOM ändern, wessen Entscheidung wird dann verwendet? Daher ist JavaScript Single-Threaded. In einem Thread wird der Code Satz für Satz abgearbeitet, bis das Programm fertig ist. Wenn in der Mitte zeitaufwändigere Vorgänge stattfinden, können Sie nur warten.

Das Single-Thread-Design macht die Ausführungseffizienz der Sprache sehr schlecht. Um die Leistung von Multi-Core-CPUs zu nutzen, unterstützt die JavaScript-Sprache asynchronen Code, wenn es zeitaufwändigere Vorgänge gibt , die Aufgabe kann für die asynchrone Ausführung geschrieben werden. Wenn die asynchrone Aufgabe nicht ausgeführt wurde, hält der Hauptthread die asynchrone Aufgabe an und führt die nachfolgende synchrone Aufgabe weiter aus. Schauen Sie dann zurück und führen Sie sie erneut aus asynchrone Aufgabe, deren Ausführung abgeschlossen ist.

Diese Art der Codeausführung passt tatsächlich zu vielen Szenen in unserem Leben. Zum Beispiel kommt Xiao Ming von der Arbeit nach Hause und möchte Wasser für Tee kochen Bei der synchronen Ausführungsmethode kocht er Wasser. Wenn das Wasser nicht kocht, wartet Xiao Ming wie ein Idiot und wartet darauf, dass das Wasser kocht, bevor er Tee zubereitet. Bei asynchroner Ausführung beginnt Xiao Ming zuerst, das Wasser zu kochen Dann geht er anderen Dingen nach, zum Beispiel fernsehen oder Musik hören. Warten Sie, bis das Wasser kocht, bevor Sie Tee kochen. Offensichtlich ist die zweite asynchrone Methode effizienter.

Was sind die häufigsten asynchronen Vorgänge? Es gibt viele, wir können ein paar gängige auflisten:

  • Ajax

  • DOM-Ereignisbetrieb

  • setTimeout

  • Promise's then-Methode

  • Knoten-Lesedatei

Wir nehmen zuerst eine Schauen Sie sich einen Code an:

//示例1
console.log(1);
setTimeout(function () {
    console.log(2);
}, 1000);
console.log(3);

Dieser Code ist sehr einfach. Fügen Sie ihn in den Browser ein und führen Sie ihn aus. Das Ergebnis ist wie folgt:

1
3
2

Weil die setTimeout-Funktion die Ausführung um 1000 verzögert Millisekunden gibt es zuerst 1 und 3 aus und nach 1000 Millisekunden wird 2 ausgegeben, was sehr logisch ist.

Lassen Sie uns den Code leicht ändern und die Verzögerungszeit von setTimeout auf 0 ändern:

//示例2
console.log(1);
setTimeout(function () {
    console.log(2);
}, 0); //0毫秒,不延时
console.log(3);

Laufende Ergebnisse:

1
3
2

Warum ist die Verzögerung von 0 Millisekunden immer noch die letzte Ausgabe von 2? Keine Sorge, schauen wir uns einen Teil des Codes an:

//示例3
console.log(1);
setTimeout(function () {
    console.log(2);
}, 0);
Promise.resolve().then(function(){
    console.log(3);
});
console.log(4);

Laufendes Ergebnis:

1
4
3
2

Für die oben genannten drei Codeteile, wenn Sie die Ergebnisse richtig schreiben und erklären können, warum das so ist Ausgabe wie diese, erklären Sie die JavaScript-Ereignisschleife sehr gut. Wenn Sie es nicht erklären können, sprechen wir darüber, was hier vor sich geht. Es ist tatsächlich sehr interessant.

Wie wird Javascript ausgeführt?

Lassen Sie uns zunächst kurz über die grundlegende Datenstruktur sprechen. Hat das etwas mit der Ereignisschleife zu tun, über die wir jetzt sprechen? Natürlich gibt es das. Das erste, was klargestellt werden muss, ist, dass der gesamte Javascript-Code auf dem Stapel ausgeführt wird , dies muss klar sein.

Wir können Code im Allgemeinen in synchronen Code und asynchronen Code unterteilen. Tatsächlich kann asynchroner Code weiter in zwei Kategorien unterteilt werden: Makroaufgaben und Mikroaufgaben.

Machen Sie sich keine Gedanken darüber, was Makroaufgaben und Mikroaufgaben sind. Oft sind solche hochrangigen Begriffe für unser Verständnis nicht förderlich: Makro bedeutet Makro und Mikro klein. .

Javascript ist eine interpretierte Sprache und ihr Ausführungsprozess ist wie folgt:

  1. 从上到下依次解释每一条js语句

  2. 若是同步任务,则压入一个栈(主线程);如果是异步任务,就放到一个任务队列里

  3. 开始执行栈里的同步任务,直到将栈里的所有任务都走完,此时栈清空了

  4. 回过头看异步队列里如果有异步任务完成了,就生成一个事件并注册回调,压入栈中

  5. 再返回第3步,直到异步队列都清空,程序运行结束

语言描述的费劲,不如看图:

Wie versteht man die Javascript-Ereignisschleife? (Bilder und Text)

通过以上的步骤可以看到,不论是同步还是异步,只要是执行的时候都是要在栈里执行的,而一遍又一遍的回头检查异步队列,这种执行方式 就是所谓的“事件环”。

明白了javascript的执行原理,我们就不难理解之前的第二段代码,为什么setTimeout为0时会最后执行,因为setTimeout是异步代码,必须要等所有的同步代码都执行完,才会执行异步队列。即使setTimeout执行得再快,它也不可能在同步代码之前执行。

浏览器中的事件环

聊了这么多,我们好像还没有说宏任务和微任务的话题呢,上面说了,异步任务又分为微任务和宏任务,那它们又是一个怎样的执行机制呢?

注意!微任务和宏任务的执行方式在浏览器和Node中有差异,有差异!重要的事我们多说几遍,以下我们讨论的是在浏览器的环境里。

在浏览器的执行环境中,总是先执行小的、微任务,再执行大的、宏任务,回过头再看看第三段代码,为什么Promise的then方法在setTimeout之前执行?其根本原理就是因为Promise的then方法是一个微任务,而setTimeout是一个宏任务。

接下来我们借用阮一峰老师的一张图来说明:

Wie versteht man die Javascript-Ereignisschleife? (Bilder und Text)

其实,以上这张图示我们可以再将它细化一点,这个图上的异步队列只画了一个,也就是说没有区分微任务队列和宏任务队列。我们可以脑补一下,在此图上多加一个微任务队列,当javascript执行时再多加一个判断,如果是微任务就加到微任务队列里,宏任务就加到宏任务队列里,在清空队列时,浏览器总会优先清空“微任务”。这样就把浏览器的事件环撤底说全了。

最后来一个大考,以下代码的运行结果是什么:

<script>
    setTimeout(function () {
        console.log(1);
        Promise.resolve().then(function () {
            console.log(2);
        });
    });
    setTimeout(function () {
        console.log(3);
    });
    Promise.resolve().then(function () {
        console.log(4);
    });
    console.log(5);
</script>

将此代码拷到chrome中跑一下,结果是:

5
4
1
2
3

不妨我们试着分析一下为什么是这个结果,首先输出5,因为console.log(5)是同步代码,这没什么可说的。

之后将前两个setTimeout和最后一个Promise放入异步队列,注意它们的区分,此时执行完了同步代码之后发现微任务和宏任务队列中都有代码,按浏览器的事件环机制,优先执行微任务,此时输出4。

然后执行宏任务队列里的第一个setTimeout,输出1。

此时,setTimeout中又有一个Promise,放入微任务队列。

再次清空微任务队列,输出2。

最后宏任务队列里还有最后一个setTimeout,输出3。

Node中的事件环

而Node中的事件环又和浏览器有些许的不同,在node.js的官方文档中有专门的描述,其中文档中有一张图,详细的说明了它的事件环机制,我们把它拿出来:

Wie versteht man die Javascript-Ereignisschleife? (Bilder und Text)

可以看到,node.js中的事件环机制分为了6个阶段,其中最重要的3个阶段我在上面做了注明:

  • timer阶段,指的就是setTimeout等宏任务

  • poll轮询阶段,如读取文件等宏任务

  • check阶段,setImmediate宏任务

图中每一个阶段都代表了一个宏任务队列,在Node事件环中,微任务的运行时机是在每一个“宏任务队列”清空之后,在进入下一个宏任务队列之间执行。这是和浏览器的最大区别。

还是用代码说话吧,有一道经典的Node.js事件环面试题:

const fs = require('fs');

fs.readFile('./1.txt', (err, data) => {
    setTimeout(() => {
        console.log('timeout');
    });
    setImmediate(() => {
        console.log('immediate');
    });
    Promise.resolve().then(() => {
        console.log('Promise');
    });
});

运行结果:

Promise
immediate
timeout

代码并不复杂,首先使用fs模块读取了一个文件,在回调的内部有两个宏任务和一个微任务,微任务总是优于宏任务执行的,因此先输出Promise。

但是之后的区别为什么先输出immdiate?原因就在于fs读取文件的宏任务在上图中的第4个轮询阶段,当第4个阶段清空队列之后,就该进入第5个check阶段,也就是setImmediate这个宏任务所在的阶段,而不会跳回第1个阶段,因此先输出immedate。

尾巴

最后总结一下,分析完浏览器和Node的事件环发现它们并不简单,但只要记住了它们之间的区别就可以分析出结果。

浏览器事件环是运行完一个宏任务马上清空微任务队列
Node事件环是清空完一个阶段的宏任务队列之后再清空微任务队列

最后,总结一下常见的宏任务和微任务:

宏任务 微任务
setTimeout Promise的then方法
setInterval process.nextTick
setImmediate MutationObserver
MessageChannel

相关推荐:

细说JavaScript事件循环机制-第二讲

javascript实现线程以及事件循环详解

Das obige ist der detaillierte Inhalt vonWie versteht man die Javascript-Ereignisschleife? (Bilder und Text). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme
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
JavaScript in Aktion: Beispiele und Projekte in realer WeltJavaScript in Aktion: Beispiele und Projekte in realer WeltApr 19, 2025 am 12:13 AM

Die Anwendung von JavaScript in der realen Welt umfasst Front-End- und Back-End-Entwicklung. 1) Zeigen Sie Front-End-Anwendungen an, indem Sie eine TODO-Listanwendung erstellen, die DOM-Operationen und Ereignisverarbeitung umfasst. 2) Erstellen Sie RESTFUFFUPI über Node.js und express, um Back-End-Anwendungen zu demonstrieren.

JavaScript und das Web: Kernfunktionalität und AnwendungsfälleJavaScript und das Web: Kernfunktionalität und AnwendungsfälleApr 18, 2025 am 12:19 AM

Zu den Hauptanwendungen von JavaScript in der Webentwicklung gehören die Interaktion der Clients, die Formüberprüfung und die asynchrone Kommunikation. 1) Dynamisches Inhaltsaktualisierung und Benutzerinteraktion durch DOM -Operationen; 2) Die Kundenüberprüfung erfolgt vor dem Einreichung von Daten, um die Benutzererfahrung zu verbessern. 3) Die Aktualisierung der Kommunikation mit dem Server wird durch AJAX -Technologie erreicht.

Verständnis der JavaScript -Engine: ImplementierungsdetailsVerständnis der JavaScript -Engine: ImplementierungsdetailsApr 17, 2025 am 12:05 AM

Es ist für Entwickler wichtig, zu verstehen, wie die JavaScript -Engine intern funktioniert, da sie effizientere Code schreibt und Leistungs Engpässe und Optimierungsstrategien verstehen kann. 1) Der Workflow der Engine umfasst drei Phasen: Parsen, Kompilieren und Ausführung; 2) Während des Ausführungsprozesses führt die Engine dynamische Optimierung durch, wie z. B. Inline -Cache und versteckte Klassen. 3) Zu Best Practices gehören die Vermeidung globaler Variablen, die Optimierung von Schleifen, die Verwendung von const und lass und die Vermeidung übermäßiger Verwendung von Schließungen.

Python vs. JavaScript: Die Lernkurve und BenutzerfreundlichkeitPython vs. JavaScript: Die Lernkurve und BenutzerfreundlichkeitApr 16, 2025 am 12:12 AM

Python eignet sich besser für Anfänger mit einer reibungslosen Lernkurve und einer kurzen Syntax. JavaScript ist für die Front-End-Entwicklung mit einer steilen Lernkurve und einer flexiblen Syntax geeignet. 1. Python-Syntax ist intuitiv und für die Entwicklung von Datenwissenschaften und Back-End-Entwicklung geeignet. 2. JavaScript ist flexibel und in Front-End- und serverseitiger Programmierung weit verbreitet.

Python gegen JavaScript: Community, Bibliotheken und RessourcenPython gegen JavaScript: Community, Bibliotheken und RessourcenApr 15, 2025 am 12:16 AM

Python und JavaScript haben ihre eigenen Vor- und Nachteile in Bezug auf Gemeinschaft, Bibliotheken und Ressourcen. 1) Die Python-Community ist freundlich und für Anfänger geeignet, aber die Front-End-Entwicklungsressourcen sind nicht so reich wie JavaScript. 2) Python ist leistungsstark in Bibliotheken für Datenwissenschaft und maschinelles Lernen, während JavaScript in Bibliotheken und Front-End-Entwicklungsbibliotheken und Frameworks besser ist. 3) Beide haben reichhaltige Lernressourcen, aber Python eignet sich zum Beginn der offiziellen Dokumente, während JavaScript mit Mdnwebdocs besser ist. Die Wahl sollte auf Projektbedürfnissen und persönlichen Interessen beruhen.

Von C/C nach JavaScript: Wie alles funktioniertVon C/C nach JavaScript: Wie alles funktioniertApr 14, 2025 am 12:05 AM

Die Verschiebung von C/C zu JavaScript erfordert die Anpassung an dynamische Typisierung, Müllsammlung und asynchrone Programmierung. 1) C/C ist eine statisch typisierte Sprache, die eine manuelle Speicherverwaltung erfordert, während JavaScript dynamisch eingegeben und die Müllsammlung automatisch verarbeitet wird. 2) C/C muss in den Maschinencode kompiliert werden, während JavaScript eine interpretierte Sprache ist. 3) JavaScript führt Konzepte wie Verschlüsse, Prototypketten und Versprechen ein, die die Flexibilität und asynchrone Programmierfunktionen verbessern.

JavaScript -Engines: Implementierungen vergleichenJavaScript -Engines: Implementierungen vergleichenApr 13, 2025 am 12:05 AM

Unterschiedliche JavaScript -Motoren haben unterschiedliche Auswirkungen beim Analysieren und Ausführen von JavaScript -Code, da sich die Implementierungsprinzipien und Optimierungsstrategien jeder Engine unterscheiden. 1. Lexikalanalyse: Quellcode in die lexikalische Einheit umwandeln. 2. Grammatikanalyse: Erzeugen Sie einen abstrakten Syntaxbaum. 3. Optimierung und Kompilierung: Generieren Sie den Maschinencode über den JIT -Compiler. 4. Führen Sie aus: Führen Sie den Maschinencode aus. V8 Engine optimiert durch sofortige Kompilierung und versteckte Klasse.

Jenseits des Browsers: JavaScript in der realen WeltJenseits des Browsers: JavaScript in der realen WeltApr 12, 2025 am 12:06 AM

Zu den Anwendungen von JavaScript in der realen Welt gehören die serverseitige Programmierung, die Entwicklung mobiler Anwendungen und das Internet der Dinge. Die serverseitige Programmierung wird über node.js realisiert, die für die hohe gleichzeitige Anfrageverarbeitung geeignet sind. 2. Die Entwicklung der mobilen Anwendungen erfolgt durch reaktnative und unterstützt die plattformübergreifende Bereitstellung. 3.. Wird für die Steuerung von IoT-Geräten über die Johnny-Five-Bibliothek verwendet, geeignet für Hardware-Interaktion.

See all articles

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ße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SecLists

SecLists

SecLists ist der ultimative Begleiter für Sicherheitstester. Dabei handelt es sich um eine Sammlung verschiedener Arten von Listen, die häufig bei Sicherheitsbewertungen verwendet werden, an einem Ort. SecLists trägt dazu bei, Sicherheitstests effizienter und produktiver zu gestalten, indem es bequem alle Listen bereitstellt, die ein Sicherheitstester benötigen könnte. Zu den Listentypen gehören Benutzernamen, Passwörter, URLs, Fuzzing-Payloads, Muster für vertrauliche Daten, Web-Shells und mehr. Der Tester kann dieses Repository einfach auf einen neuen Testcomputer übertragen und hat dann Zugriff auf alle Arten von Listen, die er benötigt.

PHPStorm Mac-Version

PHPStorm Mac-Version

Das neueste (2018.2.1) professionelle, integrierte PHP-Entwicklungstool

Herunterladen der Mac-Version des Atom-Editors

Herunterladen der Mac-Version des Atom-Editors

Der beliebteste Open-Source-Editor

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

Leistungsstarke integrierte PHP-Entwicklungsumgebung