Heim  >  Artikel  >  Web-Frontend  >  Detaillierte Einführung in setTimeout in der JS-Funktion

Detaillierte Einführung in setTimeout in der JS-Funktion

亚连
亚连Original
2018-06-19 17:29:291286Durchsuche

Dieser Artikel stellt hauptsächlich den Ausführungsprozess der js-Funktion von setTimeout vor. Freunde, die ihn benötigen, können darauf verweisen.

Um ehrlich zu sein, war ich ein wenig deprimiert, weil ich schockiert war. Warum ? Nur weil ich gerne herumblödele, habe ich zufällig diese „einfache“ Funktion gesehen:

for (var i = 0; i < 5; i++) {
      setTimeout(function () {
        console.log(i)
      }, i * 1000);
    }
    console.log(i);

Was? Ist das nicht die Implementierungsmethode, die ich vor langer Zeit gesehen habe, nämlich eine 5, dann eine 5 und dann jede Sekunde eine 5 zu drucken, bis 6 5er gedruckt sind? Hier kommt also die Frage: Was soll ich tun, wenn ich 0,1,2,3,4,5 nacheinander drucken möchte? Tatsächlich wusste ich vorher, dass es zwei Methoden gibt: Eine sieht so aus:

function log(i){
setTimeout(function(){
console.log(i)
},i*1000)
};
for (var i = 0; i < 5; i++) {
      log(i) ;
    }
    console.log(i);

Eine andere ist so:

for(var i=0;i<5;i++){
(function(e){
setTimeout(function(){
console.log(e)
},i*1000);
})(i);
};
console.log(i);

Ich habe keine Angst vor Witzen. Davor habe ich nicht verstanden, wofür diese beiden Funktionen wirklich verwendet wurden. Ich habe mich nur dazu gezwungen, mich daran zu erinnern und sie zu ändern Es ist in Ordnung, aber jetzt habe ich keine Zwangsstörung! Also habe ich es langsam analysiert und festgestellt, dass der obige Code wie folgt unterteilt werden kann:

Wenn i=0; die Bedingung erfüllt ist;

setTimeout(function(){
console.log(i)
},0*1000);

i=2;

setTimeout(function(){
console.log(i)
},1*1000);

i=3;

setTimeout(function(){
console.log(i)
},2*1000);
Wenn i=5 ist, ist die Bedingung nicht erfüllt, springen Sie aus der Schleife und führen Sie dann console.log(i) nach der for-Schleife aus. Drucken Sie schließlich 5 aus.

Das ist es Wirklich interessant, warum wird die Konsole in setTimeout nach console.log außerhalb der for-Schleife ausgeführt? Bis ich das Wort => „Warteschlange“ erkannte, sind Warteschlangen in Makroaufgabenwarteschlange (Makroaufgabe) und Mikroaufgabenwarteschlange (Mikroaufgabe) unterteilt. In Javascript:

Makroaufgabe enthält: Skript (Gesamtcode). , setTimeout, setInterval, setImmediate, I/O, UI-Rendering.

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

Das setTimeout der obigen Funktion gehört zur Makroaufgabe

In js die Reihenfolge der Ereignisschleife Die erste Schleife beginnt mit dem Skript, und dann gelangt der globale Kontext in den Funktionsaufrufstapel. Wenn eine Makroaufgabe auftritt, wird sie an das Modul übergeben, das sie verarbeitet. Nach der Verarbeitung wird die Rückruffunktion eingefügt die Warteschlange der Makroaufgabe. Wenn eine Mikroaufgabe auftritt, stellt -task auch seine Rückruffunktion in die Mikroaufgabenwarteschlange. 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.

Aus diesem Grund wird das console.log innerhalb von setTimeout nach dem console.log außerhalb der for-Schleife ausgeführt. Im Funktionsausführungskontext wird die seiTimeout-Funktion in die Warteschlange gestellt, um ihre Makroaufgabe zu verarbeiten. , sodass die Funktion in setTimeout nicht während der Schleife ausgeführt wird, sondern wartet, bis der gesamte Code (nicht in der Warteschlange) ausgeführt wird, bevor die Funktion in der Warteschlange ausgeführt wird. Beim Schreiben bin ich möglicherweise etwas verwirrt Tatsächlich bin ich auch etwas verwirrt, hahaha! !

Um Ihr Verständnis zu vertiefen, können Sie auch versuchen, Promise hinzuzufügen. Hier ist Folgendes:

setTimeout(function(){
console.log(i)
},3*1000);

Erklären Sie es=>

1 Quelle der Skriptaufgabe: Wird zuerst ausgeführt, wird der globale Kontext auf den Stapel verschoben.

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

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 nicht in die Warteschlange gestellt wird, wenn sie direkt ausgeführt wird, sodass zu diesem Zeitpunkt 1 ausgegeben wird.

4. Wenn Sie in der for-Schleife auf die Auflösungsfunktion stoßen, wird die Funktion in den Stapel verschoben und dann herausgeholt. Zu diesem Zeitpunkt wird der Status „Versprechen“ erfüllt. Der Code wird dann ausgeführt und trifft auf console.log(2), das 2 ausgibt.

5. Dann trifft der Code auf die Methode then und ihre Rückruffunktion wird als Mikroaufgabe auf den Stapel verschoben und in die Aufgabenwarteschlange von Promise eingegeben von Promise und der Funktion in setTimeout Die Rückruffunktionen haben die gleiche Bedeutung und werden in ihre jeweiligen Aufgabenwarteschlangen gestellt

Sie werden erst ausgeführt, wenn der Funktionskontext, also der gesamte Nicht-Warteschlangencode in Skript, wurde ausgeführt. Darüber hinaus hat die Mikrotask-Warteschlange Vorrang vor der Makrotask-Warteschlangenverarbeitung,

Die Gesamtreihenfolge ist: Kontext-Nicht-Warteschlangencode > Rückruffunktionscode der Mikrotask-Warteschlange > Rückruffunktionscode der Makrotask-Warteschlange

6. Der Code wird weiterhin ausgeführt und die Konsole wird zu diesem Zeitpunkt auf log(3) gestoßen, Ausgabe 3.

7. Nach der Ausgabe von 3 wird der Code des ersten Makrotask-Skripts ausgeführt. Zu diesem Zeitpunkt beginnen alle Mikrotasks in der Warteschlange ausgeführt zu werden. Die Rückruffunktion wird auf den Stapel verschoben und dann ausgegeben. Zu diesem Zeitpunkt sind alle Mikroaufgaben abgeschlossen und die erste Runde der Schleife endet. Die zweite Runde der Schleife beginnt mit der Rückruffunktion von setTimeout und wird in den Stapel verschoben. Zu diesem Zeitpunkt wird 4 ausgegeben.

Um Ihr Verständnis zu vertiefen, hier noch ein weiterer Code:

setTimeout(function(){
console.log(i)
},4*1000);

Wenn Ihr Ausführungsergebnis lautet: golb1=>glob1_promise=>glob1_then=>timeout1=> ;timeout1_promise=> ;timeout1_then=>prp_timeout=>time_timeout=>timeout1_timeout1,

Vielleicht ist die asynchrone Warteschlange eine Einführung! ~~Der obige Code sieht etwas chaotisch aus. Es ist vielleicht besser, Asyns zu verwenden und auf die Transformation zu warten, aber das ist mehr oder weniger die Erkenntnis, die ich von setTimeout erhalten habe.

Das Obige ist das, was ich für alle kompiliert habe. Ich hoffe, dass es in Zukunft für alle hilfreich sein wird.

Verwandte Artikel:

So implementieren Sie das WeChat Jump Game mit Three.js

Detaillierte Einführung in die http-Implementierung in NODEJS

So implementieren Sie die Chat-Funktion mit nodejs

So verwenden Sie erweiterte Funktionen in JavaScript

Mit Angular5 Implementierung der serverseitigen Rendering-Praxis

So setzen Sie den Ruhezustand in vuex zurück

Das obige ist der detaillierte Inhalt vonDetaillierte Einführung in setTimeout in der JS-Funktion. 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