Heim  >  Artikel  >  Web-Frontend  >  Detaillierte Erläuterung des JavaScript-Ereignisschleifenmechanismus – Vorlesung 2

Detaillierte Erläuterung des JavaScript-Ereignisschleifenmechanismus – Vorlesung 2

韦小宝
韦小宝Original
2018-03-07 15:26:321822Durchsuche

Lassen Sie uns weiter über den Ereignisschleifenmechanismus in JavaScript sprechen. Der erste Vortrag über den JavaScript-Ereignis-Schleifenmechanismus ist noch nicht abgeschlossen Mechanismus jetzt lesen Sie diesen Artikel weiter!

Im letzten Artikel habe ich eine allgemeine Einführung in den Ereignisschleifenmechanismus von JavaScript gegeben, aber am Ende blieben mir ein Teil des Codes und mehrere Fragen übrig.

Beginnen wir zuerst mit diesem Code

(function test() {
    setTimeout(function() {console.log(4)}, 0);
    new Promise(function executor(resolve) {
        console.log(1);
        for( var i=0 ; i<10000 ; i++ ) {
            i == 9999 && resolve();
        }
        console.log(2);
    }).then(function() {
        console.log(5);
    });
    console.log(3);
})()

In diesem Code werden setTimeout und Promise beide Aufgabenquellen genannt und stammen aus unterschiedlichen AufgabenquellenDie Rückruffunktion werden in verschiedene Aufgabenwarteschlangen gestellt.

Die Rückruffunktion von setTimeout wird in die Aufgabenwarteschlange von setTimeout gestellt. Bei Promise ist die Rückruffunktion nicht die übergebene Executor-Funktion, sondern die Parameter in der asynchron ausgeführten then-Methode, die in die Aufgabenwarteschlange von Promise gestellt werden. Mit anderen Worten, der erste Parameter von Promise wird nicht in die Promise-Aufgabenwarteschlange gestellt, sondern in der aktuellen Warteschlange ausgeführt.

Die Aufgabenwarteschlangen von setTimeout und Promise werden Makroaufgaben (Makroaufgaben) genannt. Natürlich gibt es unserer Meinung nach auch Mikroaufgaben (Mikroaufgaben).

  1. Makroaufgabe umfasst: Skript (Gesamtcode), setTimeout, setInterval, setImmediate, I/O, UI-Rendering.

  2. Mikroaufgabe umfasst: Process.nextTick, Promises, Object.observe, MutationObserver

Das obige SetImmediate und Process.nextTick sind Node The Die API in .JS ist im Browser nicht verfügbar. Hier ist nur ein Beispiel. Sie müssen sich keine Gedanken über die Implementierung machen.

Die Reihenfolge der Ereignisschleife besteht darin, die erste Schleife vom Skript aus zu starten und dann den globalen Kontext in den Funktionsaufrufstapel einzugeben und ihn an das Modul zu übergeben, das ihn verarbeitet. Nach der Verarbeitung wird die Rückruffunktion in das Makro gestellt. Wenn eine Mikroaufgabe auftritt, wird auch deren Rückruffunktion in die Mikroaufgabenwarteschlange gestellt. Bis der Funktionsaufrufstapel gelöscht ist und nur noch der globale Ausführungskontext übrig ist, werden alle Mikroaufgaben ausgeführt. Nachdem alle ausführbaren Mikroaufgaben ausgeführt wurden. Die Schleife führt erneut eine Aufgabenwarteschlange in der Makroaufgabe aus und führt dann nach der Ausführung alle Mikroaufgaben aus, und die Schleife wird so fortgesetzt.

Analyse des Ausführungsprozesses

Die folgenden Analyseideen folgen dem, was Herr Bo zuvor geschrieben hat, und gehen tief in den Kern um die Ereignisse im Ereignisschleifenmechanismus im Detail zu erklären.

Verwenden Sie die vorherige Kastanie als Analyseobjekt, um zu analysieren, wie der Ereignisschleifenmechanismus den Code ausführt

(function test() {
    setTimeout(function() {console.log(4)}, 0);
    new Promise(function executor(resolve) {
        console.log(1);
        for( var i=0 ; i<10000 ; i++ ) {
            i == 9999 && resolve();
        }
        console.log(2);
    }).then(function() {
        console.log(5);
    });
    console.log(3);
})()

Achten Sie auf das setTimeout-Aufgabenteam und das letzte insgesamt Die folgenden Bilder: Im Funktionsaufrufstapel gespeichert sind die Rückruffunktionen von setTimeout, nicht der gesamte setTimeout-Timer.

Detaillierte Erläuterung des JavaScript-Ereignisschleifenmechanismus – Vorlesung 2

Zuerst wird die Skript-Aufgabenquelle ausgeführt und der globale Kontext auf den Stapel verschoben.

Detaillierte Erläuterung des JavaScript-Ereignisschleifenmechanismus – Vorlesung 2

2. Der Quellcode der Skriptaufgabe stößt während der Ausführung auf setTimeout. Als Makroaufgabe stellt er seine Rückruffunktion in eine eigene Warteschlange.

Detaillierte Erläuterung des JavaScript-Ereignisschleifenmechanismus – Vorlesung 2

3. Der Code der Skriptaufgabenquelle trifft während der Ausführung auf eine Promise-Instanz. Der erste Parameter im Promise-Konstruktor ist, dass die aktuelle Aufgabe bei direkter Ausführung nicht in die Warteschlange gestellt wird, sodass zu diesem Zeitpunkt 1 ausgegeben wird.

Detaillierte Erläuterung des JavaScript-Ereignisschleifenmechanismus – Vorlesung 2

Detaillierte Erläuterung des JavaScript-Ereignisschleifenmechanismus – Vorlesung 2

4. Wenn Sie in der for-Schleife auf die Auflösungsfunktion stoßen, wird die Funktion in den Stapel verschoben und erscheint dann, wenn der Status des Versprechens „Erfüllt“ wird. Der Code wird dann ausgeführt und trifft auf console.log(2), das 2 ausgibt.

Detaillierte Erläuterung des JavaScript-Ereignisschleifenmechanismus – Vorlesung 2

5. Dann trifft der Code auf die then-Methode und ihre Rückruffunktion wird als Mikroaufgabe auf den Stapel verschoben und in die Promise-Aufgabenwarteschlange eingegeben.

Detaillierte Erläuterung des JavaScript-Ereignisschleifenmechanismus – Vorlesung 2

6. Der Code wird dann ausgeführt. Zu diesem Zeitpunkt wird console.log(3) angetroffen und 3 ausgegeben.

Detaillierte Erläuterung des JavaScript-Ereignisschleifenmechanismus – Vorlesung 2Detaillierte Erläuterung des JavaScript-Ereignisschleifenmechanismus – Vorlesung 2

7.输出3之后第一个宏任务script的代码执行完毕,这时候开始开始执行所有在队列之中的micro-task。then的回调函数入栈执行完毕之后出栈,这时候输出5

Detaillierte Erläuterung des JavaScript-Ereignisschleifenmechanismus – Vorlesung 2

8.这时候所有的micro-task执行完毕,第一轮循环结束。第二轮循环从setTimeout的任务队列开始,setTimeout的回调函数入栈执行完毕之后出栈,此时输出4。

总结

总的来说就是:

1、不同的任务会放进不同的任务队列之中。

2、先执行macro-task,等到函数调用栈清空之后再执行所有在队列之中的micro-task。

3、等到所有micro-task执行完之后再从macro-task中的一个任务队列开始执行,就这样一直循环。

4、当有多个macro-task(micro-task)队列时,事件循环的顺序是按上文macro-task(micro-task)的分类中书写的顺序执行的。

测试

说到这里,我们应该都明白了,下面是一个复杂的代码段(改自深入核心,详解事件循环机制),里面有混杂着的micro-task和macro-task,自己画图试试流程哇,然后再用node执行看看输出的顺序是否一致。

console.log(&#39;golb1&#39;);
setImmediate(function() {
    console.log(&#39;immediate1&#39;);
    process.nextTick(function() {
        console.log(&#39;immediate1_nextTick&#39;);
    })
    new Promise(function(resolve) {
        console.log(&#39;immediate1_promise&#39;);
        resolve();
    }).then(function() {
        console.log(&#39;immediate1_then&#39;)
    })
})
setTimeout(function() {
    console.log(&#39;timeout1&#39;);
    process.nextTick(function() {
        console.log(&#39;timeout1_nextTick&#39;);
    })
    new Promise(function(resolve) {
        console.log(&#39;timeout1_promise&#39;);
        resolve();
    }).then(function() {
        console.log(&#39;timeout1_then&#39;)
    })
    setTimeout(function() {
    	console.log(&#39;timeout1_timeout1&#39;);
    process.nextTick(function() {
        console.log(&#39;timeout1_timeout1_nextTick&#39;);
    })
    setImmediate(function() {
    	console.log(&#39;timeout1_setImmediate1&#39;);
    })
    });
})
new Promise(function(resolve) {
    console.log(&#39;glob1_promise&#39;);
    resolve();
}).then(function() {
    console.log(&#39;glob1_then&#39;)
})
process.nextTick(function() {
    console.log(&#39;glob1_nextTick&#39;);
})

讲到这里我们的细说JavaScript事件循环机制也就正式讲完了,看不懂了两篇结合起来看看,练练即可!

先看看我吧:

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

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung des JavaScript-Ereignisschleifenmechanismus – Vorlesung 2. 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