Eine kurze Diskussion über die Ausführungsreihenfolge von JavaScript-Makrotasks und Mikrotasks

Eine kurze Diskussion über die Ausführungsreihenfolge von JavaScript-Makrotasks und Mikrotasks

1. JavaScript ist Single-Threaded

JavaScript ist ein Single-Thread-Programm, was bedeutet, dass es immer nur eine Sache gleichzeitig tun kann und die nächste Sache erst ausgeführt werden kann, wenn die vorherige abgeschlossen ist. Dies hat zur Folge, dass der nachfolgende Code nicht ausgeführt werden kann, wenn eine zeitaufwändige Aufgabe auftritt.

Zuvor müssen wir Synchronisation und Asynchronität verstehen

1. Synchrone Aufgaben

    konsole.log(123);
    konsole.log(456);
    für (lass i = 1; i <= 5; i++) {
      konsole.log(i);
    } 

Wie der Name schon sagt, muss es sequentiell ausgeführt werden

2. Asynchrone Aufgaben

    setzeTimeout(() => {
      Konsole.log('Timer');
    }, 0)
    console.log('Ultraman');

Gemäß der normalen Ausführungsreihenfolge steht der Timer oben, daher sollte zuerst der Timer und dann Ultraman ausgegeben werden.

Das Endergebnis ist, dass zuerst Ultraman und dann der Timer ausgegeben wird. Der Grund dafür ist, dass setTimeout eine asynchrone Aufgabe ist.

Noch eine Information: Der Timer von setTimeout ist asynchron, egal wie viele Millisekunden er verzögert wird. Die Zeit ist auch bei jedem Browser anders. Jeder Browser hat seine eigenen Unterschiede, aber das Minimum ist als 0 und 4 Millisekunden definiert.

2. Aufgabenwarteschlange

Aus dem obigen Code wissen wir, dass setTimeout asynchron ist. Wir können die Priorität der Ausführungsreihenfolge verstehen: synchroner Code > asynchroner Code. Daher ist die Aufgabenwarteschlange in zwei Kategorien unterteilt: 1. synchrone Aufgaben 2. asynchrone Aufgaben

1. Ausführungsstapel

(1) Alle synchronen Aufgaben werden auf dem Hauptthread ausgeführt und bilden einen Ausführungskontextstapel.

(2) Neben dem Hauptthread gibt es auch eine „Task-Warteschlange“. Solange die asynchrone Aufgabe ein laufendes Ergebnis hat, wird ein Ereignis in die „Aufgabenwarteschlange“ gestellt.

(3) Sobald alle synchronen Aufgaben im „Ausführungsstapel“ ausgeführt wurden, liest das System die „Aufgabenwarteschlange“, um zu sehen, welche Ereignisse sich darin befinden. Die entsprechenden asynchronen Aufgaben beenden dann den Wartezustand, gelangen in den Ausführungsstapel und beginnen mit der Ausführung.

(4) Der Hauptthread wiederholt den dritten Schritt von oben kontinuierlich. Dies wird als Ereignisschleife bezeichnet.

Gib einfach eine Birne

Sie gehen beide auswärts essen, aber P2 spart die Zeit des Ausgehens.

Nach einem kurzen Verständnis wollen wir einen genaueren Blick auf Makrotasks und Mikrotasks in asynchronen Aufgaben werfen.

Persönliches Verständnis: Makrotasks und Mikrotasks können als zwei Formen der Asynchronität verstanden werden. Asynchronität hat zwei untergeordnete Elemente: Makrotasks und Mikrotasks.

Methoden in Makroaufgaben: 1. Skript (kann als äußerer Synchronisationscode, als Einstiegspunkt verstanden werden) 2. setTimeout/setInterval

Methoden in Mikrotasks: 1. Promise 2. nextTick

Die Reihenfolge ihrer Ausführung ist, dass zuerst Mikrotasks und dann Makrotasks ausgegeben werden.

Code sagen ohne Beweise

    setzeTimeout(() => {
      Konsole.log('Timer');
    }, 0)
    neues Versprechen((lösen) => {
      console.log('synchroner Code')  
      lösen('asynchroner Code')
    }).then((res) => {
      konsole.log(res);   
    })
    console.log('Ultraman'); 

Beachten Sie, dass new Promise einen Konstruktor erstellt, der ein synchroner Prozess ist, während die .then-Methode asynchron ist, sodass der Code zuerst synchron ausgeführt wird > Mikrotask > Makrotask

Um den Ausführungsprozess detaillierter zu beschreiben, ist das folgende Diagramm etwas komplizierter.

Diese Bilder werden kombiniert

Erweitern Sie Ihr Verständnis von setTimeout

Frage 1: Beginnt setTimeout nach der Ausführung des synchronen Codes wieder bei 0 zu zählen?

    setzeTimeout(() => {
      console.log('Zeitüberschreitung festlegen');
    }, 1000);
    console.log('Ultraman');
    für (sei i = 0; i < 1000; i++) {
      konsole.log('');
    } 

An dieser Stelle möchte ich darauf hinweisen, dass setTimeout, wenn ich mich in der for-Schleife befinde, auch ein Timer-Modul startet. Wenn also der Hauptthread ausgeführt wird, hat das Timer-Modul bereits mit der Ausführung begonnen, sodass es nicht 1 Sekunde auf die Ausführung warten muss.

(Gehen Sie nicht davon aus, dass die Synchronisierung abgeschlossen ist und beginnen Sie dann mit der Zeitmessung.)

Frage 2: Soll von den beiden Timern zuerst der obere Timer und dann der untere Timer ausgeführt werden?

Für den Test müssen wir lediglich einen Timer hinzufügen, um zu sehen, wer zuerst ausführt.

    setzeTimeout(() => {
      console.log('setTimeout1');
    }, 2000);
    setzeTimeout(() => {
      console.log('setTimeout2');
    }, 1000); 

Es stellt sich heraus, dass, wenn es zwei Timer gibt, der mit der kürzeren Zeit zuerst im Hauptthread ausgeführt wird.

Frage 3: Wenn eine Variable als 0 definiert ist und zwei identische Timer-Ereignisse festgelegt werden, was ist die Ausgabe? (Interviewfrage)

    ich = 0
    setzeTimeout(() => {
      konsole.log(++i); //1
    }, 1000);
    setzeTimeout(() => {
      konsole.log(++i); //2 
    }, 1000);

Jetzt müssen Sie wissen, dass Timer-Makroaufgaben nicht zusammen, sondern nacheinander ausgeführt werden! !

Interviewfragen zur Ausführungsreihenfolge von Makrotasks und Mikrotasks

    konsole.log('1');
 
    setzeTimeout(Funktion () {
      konsole.log('2');
      Prozess.nextTick(Funktion () {
        konsole.log('3');
      })
      neues Versprechen (Funktion (Auflösung) {
        konsole.log('4');
        lösen();
      }).dann(Funktion () {
        konsole.log('5')
      })
    })
    Prozess.nextTick(Funktion () {
      konsole.log('6');
    })
    neues Versprechen (Funktion (Auflösung) {
      konsole.log('7');
      lösen();
    }).dann(Funktion () {
      konsole.log('8')
    })
 
    setzeTimeout(Funktion () {
      konsole.log('9');
      Prozess.nextTick(Funktion () {
        konsole.log('10');
      })
      neues Versprechen (Funktion (Auflösung) {
        konsole.log('11');
        lösen();
      }).dann(Funktion () {
        konsole.log('12')
      })
    })

Antwort:

Die erste Ausführungsrunde des externen Synchronisationscodes: 1 7

Zweite Runde der Mikrotask-Ausführung: 6 8

Die dritte Runde der Makrotasks: Erstes setTimeout: Synchronisation 2 4 Mikrotask 3 5 Zweites setTimeout: Synchronisation 9 11 Mikrotask 10 12

Gesamtantwort: 1, 7, 6, 8, 2, 4, 3, 5, 9, 11, 10, 12

Damit ist dieser Artikel zur Ausführungsreihenfolge von JavaScript-Makrotasks und -Mikrotasks abgeschlossen. Weitere Informationen zur Ausführungsreihenfolge von JavaScript-Makrotasks und -Mikrotasks finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen!

Das könnte Sie auch interessieren:
  • Details zu Makrotasks und Mikrotasks in JavaScript
  • Eine kurze Diskussion über Makrotasks und Mikrotasks in js
  • JavaScript-Makrotasks und Mikrotasks
  • Eine kurze Diskussion über die Prinzipien von JavaScript-Ereignisschleifen-Mikrotasks und Makrotask-Warteschlangen
  • Analyse der JavaScript-Ereignisschleife sowie der Prinzipien von Makro- und Mikro-Tasks
  • JS-Ereignisschleifenmechanismus Ereignisschleifen-Makrotask-Mikrotask-Prinzipanalyse
  • Erläuterung von JavaScript-Mikrotasks und Makrotasks

<<:  Zusammenfassung der Kenntnisse und der Verwendung von Linux-VI-Befehlen

>>:  Eine vollständige Liste häufig verwendeter MySQL-Funktionen (klassifiziert und zusammengefasst)

Artikel empfehlen

Fabric.js implementiert DIY-Postkartenfunktion

In diesem Artikel wird der spezifische Code von F...

Ursachen und Lösungen für den Nginx 502 Bad Gateway-Fehler

Der Nginx 502 Bad Gateway-Fehler ist mir schon me...

Nodejs konvertiert JSON-String in JSON-Objekt-Fehlerlösung

Wie konvertiere ich eine JSON-Zeichenfolge in ein...

Architektur und Komponentenbeschreibung der privaten Docker-Bibliothek Harbor

In diesem Artikel wird die Zusammensetzung der Ha...

jQuery implementiert einen einfachen Karusselleffekt

Hallo zusammen, heute werde ich die Implementieru...

jQuery erzielt Ein- und Ausblendeffekte

Bevor wir jQuery verwenden, um den Ein- und Ausbl...

JavaScript-Singleton-Modus zum Implementieren benutzerdefinierter Popup-Fenster

In diesem Artikel wird der spezifische Code des J...

Beispielcode für Nginx zur Erreichung dynamischer und statischer Trennung

1. Einfache Konfiguration der dynamischen und sta...

CSS verwendet das Autoflow-Attribut, um einen Sitzauswahleffekt zu erzielen

1. Autoflow-Attribut: Wenn die Länge und Breite d...

CSS-Beispielcode zum Ausblenden der Bildlaufleiste und Scrollen des Inhalts

Vorwort Wenn die HTML-Struktur einer Seite viele ...

JavaScript-Canvas zum Laden von Bildern

In diesem Artikel wird der spezifische Code von J...

Beispielcode zum Ändern des Textstils der Eingabeaufforderung in HTML

Auf vielen Websites wird im Eingabefeld Hinweiste...

So verstecken Sie RAR-Dateien in Bildern

Sie können dieses Logo lokal als .rar-Datei speic...