JS-Prinzip der asynchronen Ausführung und Rückrufdetails

JS-Prinzip der asynchronen Ausführung und Rückrufdetails

1. JS-Prinzip der asynchronen Ausführung

Wir wissen, dass JavaScript ein Single-Thread ist, während Browser mehrthreadig sind. Single-Thread-Ausführungsaufgaben müssen einzeln in die Warteschlange gestellt werden. Wenn die Ausführung einer Aufgabe lange dauert (z. B. dauert Ajax lange), führt dies direkt dazu, dass keine Antwort erfolgt und die nachfolgenden Aufgaben auf die Ausführung warten. Hier kommt die Asynchronität ins Spiel.

Um Asynchronität zu verstehen, müssen wir zunächst wissen, dass der Browser über drei grundlegende residente Threads verfügt: einen JS-Engine-Thread, einen ereignisauslösenden Thread und einen GUI-Rendering-Thread.

Der JS-Engine-Thread und der ereignisauslösende Thread bilden zusammen einen Ereignisschleifenmechanismus, und der GUI-Rendering-Thread und die JS-Engine schließen sich gegenseitig aus. Wenn die JS-Engine ausgeführt wird, wird der GUI-Thread angehalten und die GUI-Updates werden in einer Warteschlange gespeichert und sofort ausgeführt, wenn die JS-Engine im Leerlauf ist.

Wir analysieren es anhand seines Ereignisschleifenmechanismus:

Der Thread der JS-Engine ist in synchrone und asynchrone Aufgaben unterteilt:

1. Alle Synchronisierungsaufgaben werden über den Hauptthread ausgeführt, um einen Ausführungsstapel zu bilden.

2. Wenn eine asynchrone Aufgabe vorliegt, wird sie an den asynchronen Prozess (WebAPIs) übergeben: einschließlich ereignisauslösender Thread- oder Timer-Thread-Verarbeitung, um eine Aufgabenwarteschlange zu bilden.

3. Wenn alle Aufgaben im Ausführungsstapel verarbeitet sind und der Hauptthread inaktiv ist, werden Aufgaben aus der Aufgabenwarteschlange extrahiert und im Ausführungsstapel ausgeführt.

Einfach ausgedrückt verfügt JavaScript neben dem Hauptthread auch über eine Aufgabenwarteschlange. In der Aufgabenwarteschlange werden Inhalte gespeichert, die asynchron ausgeführt werden müssen. Nachdem der Hauptthread ausgeführt wurde, werden die Aufgaben in der Aufgabenwarteschlange kontinuierlich gescannt und ausgeführt, bis die Warteschlange leer ist.

Bilderklärung:

Wie in der Abbildung gezeigt, stellt Xiao Ming das Lernen in die asynchrone Aufgabenwarteschlange, da das Lernen lange dauert und er das DNF-Spiel nicht spielen kann, wenn er es nicht beendet. Er wird lernen (Aufgabenwarteschlange), nachdem er das Spiel beendet hat (Hauptthread). Während dieser Zeit fügt die Mutter Lernereignisse (DOM-Ereignisse) hinzu. Jedes Mal, wenn Xiao Ming eine Lernaufgabe erledigt, prüft er, welche anderen Aufgaben es gibt (Loop-Scanning), bis er sie erledigt.

Schauen wir uns ein weiteres Beispiel an (der Browser wird aktualisiert und klickt kontinuierlich auf die Schaltfläche):

  let myData = null
  //Ajax-Anforderungsfunktion ajax() {
  //Tencent COVID-19 Echtzeit-Datenschnittstelle, nur zum Lernen axios.get('https://api.inews.qq.com/newsqa/v1/query/inner/publish/modules/list?modules=chinaDayList,chinaDayAddList,nowConfirmStatis,provinceCompare')
   .dann(data => {
   console.log("ajax kehrt erfolgreich zurück");
   meineDaten = Daten.Daten
   console.log(meineDaten);

   })
   .catch(Fehler => {
   console.log("Ajax-Rückgabe fehlgeschlagen");
   })
  }
  console.log(meineDaten);
  ajax()
  setzeTimeout(() => {
  Konsole.log('Timer');
  }, 2000);
  console.log(meineDaten);
  const btn = document.querySelector('Schaltfläche')
  btn.onclick = () => {
  console.log("geklickt");
  }

Null
Null
Ajax gibt Erfolg zurück
Objekt
Habe den Timer angeklickt

Wie Sie sehen, wird die Konsole synchron im Hauptthread ausgeführt und zuerst ausgeführt, während die Task-Warteschlange außerhalb des Hauptthreads den asynchron ausgeführten Inhalt speichert, nämlich SetTimeout-, Ajax- und DOM-Ereignisse, die in der Reihenfolge der Task-Warteschlange (Loop-Scanning-Warteschlange) ausgeführt werden.

Warum müssen wir in einer Schleife scannen?

Aus dem Klickereignis ist ersichtlich, dass bei Benutzerinteraktionen (Klickereignisse, Bildlaufereignisse, Ereignisse zur Änderung der Fenstergröße usw.) neue Ereignisse zur Aufgabenwarteschlange in der Ereignisschleife hinzugefügt werden und dann auf die Ausführung warten, sodass ein zyklischer Scan erforderlich ist.

2. Rückrufe in JS Asynchrony

Da alle asynchronen Vorgänge in der letzten Aufgabenwarteschlange ausgeführt werden, sind viele unserer Logiken schwer zu implementieren. Derzeit müssen wir diese asynchrone Logik verarbeiten. Die gebräuchlichste Methode ist Callback – Rückruf.

Rückruffunktion: Einfach ausgedrückt: Wenn Funktion A Funktion B als Parameter übergibt, wird Funktion B zur Rückruffunktion, die von Funktion A ausgeführt wird. Es gibt zwei Arten von Rückrufen: verschachtelte Rückrufe und verkettete Rückrufe.

Hier ist eine einfache Verwendung des Rückrufs:

   let myData = null
   console.log(meineDaten);
   setzeTimeout(() => {
    Konsole.log('Timer');
   }, 2000);
   const btn = document.querySelector('Schaltfläche')
   btn.onclick = () => {
    console.log("geklickt");
   }
   lass name = "Zhang San"
   Funktion hr(Rückruf) {
    setzeTimeout(() => {
     console.log(`Ich bin ${name}`);
     Rückruf();
    }, 2001);
   }
   console.log(meineDaten);
   Funktion gj() {
    console.log(`${name} Hallo, ich bin Li Si, lass uns einander kennenlernen`);
   }
   Std.(gj)

Null
Null
Habe den Timer angeklickt. Ich bin Zhang San. Hallo, ich bin Li Si. Lernen wir uns kennen. Geklickt

Es ist offensichtlich, dass ein Rückruf verwendet wird, wenn unsere Funktion Daten verwenden muss. Hier wird ein asynchroner Rückruf verwendet.

Obwohl Callbacks eine gängige Methode zum Lösen von Asynchronität sind, gehen damit zunehmend komplexere Anforderungen an JS einher. Synchron und asynchron erfordern immer mehr Rückrufe, um Logik zu implementieren. Die Mischung aus synchronen und asynchronen Vorgängen sowie die übermäßige Verschachtelung und Einrückung von Rückrufen erschweren die Interpretation und Wartung des Codes und bilden eine „Rückruf-Hölle“.

Schauen wir uns ein Beispiel an:

const verifyUser = function(Benutzername, Passwort, Rückruf){
  dataBase.verifyUser(Benutzername, Passwort, (Fehler, Benutzerinfo) => {
    if (Fehler) {
      Rückruf (Fehler)
    }anders{
      dataBase.getRoles(Benutzername, (Fehler, Rollen) => {
        wenn (Fehler){
          Rückruf (Fehler)
        }anders {
          dataBase.logAccess(Benutzername, (Fehler) => {
            wenn (Fehler){
              Rückruf (Fehler);
            }anders{
              Rückruf (null, Benutzerinfo, Rollen);
            }
          })
        }
      })
    }
  })
};

Die meisten Leute bekommen schon beim bloßen Anschauen des obigen Codes einen Nervenzusammenbruch. Wenn ein Projekt Hunderte solcher Codeblöcke enthält, glaube ich, dass selbst die Person, die es geschrieben hat, nach einer Weile Kopfschmerzen bekommt. Zu meinem eigenen Projekt zu kommen, ist wie in die Hölle zu kommen.

Das Wichtigste ist, dass es gleichzeitig ein Vertrauensproblem mit dem Rückruf gibt, da er die Ausführungskontrolle an einen Dritten (wie etwa Ajax) übergibt. Um das Vertrauensproblem zu lösen, müssen wir verschiedene Logiken in das Programm schreiben, um das durch Rückrufe verursachte Vertrauensproblem zu lösen.

Zu früh anrufen

·Anruf abgeschlossen

Die Anzahl der Aufrufe ist zu hoch oder zu niedrig und die erforderlichen Parameter werden nicht erfolgreich an die Rückruffunktion übergeben.

Mögliche Fehler werden geschluckt.

Es zeigt sich, dass das Schreiben einer bestimmten Logik zur Lösung bestimmter Vertrauensprobleme den Schwierigkeitsgrad höher macht als den Anwendungsnutzen selbst und außerdem zu Problemen wie redundantem Code und schlechter Lesbarkeit führt.

Zusammenfassend: Rückrufe lösen asynchrone Probleme:

1) Es entspricht nicht dem logischen Denken der Menschen bei der Aufgabenbearbeitung

2) Vertrauensprobleme durch Rückrufe.

Angesichts der immer offensichtlicheren Nachteile von Rückrufen hat ES6 Promise aktualisiert, um asynchrone Probleme zu lösen. Der nächste Artikel handelt von ES6 – Promise.

Zusammenfassen

Dies ist das Ende dieses Artikels über das Prinzip der asynchronen Ausführung und den Rückruf von JS. Weitere relevante Inhalte zum Prinzip der asynchronen Ausführung und zum Rückruf von JS finden Sie in den vorherigen Artikeln von 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

Das könnte Sie auch interessieren:
  • Detaillierte Erläuterung der asynchronen Prozessimplementierung in Single-Thread-JavaScript
  • Analysieren Sie die Eigenschaften des asynchronen IO-Rückrufs mit einem Thread in JS
  • Asynchrone Programmierung in Javascript: Verstehen Sie Promise wirklich?
  • Detaillierte Erläuterung der ersten Verwendung von Promise in der asynchronen JavaScript-Programmierung
  • So schreiben Sie asynchrone Aufgaben in modernem JavaScript
  • Detaillierte Erklärung asynchroner Generatoren und asynchroner Iterationen in Node.js
  • Lernen Sie die asynchrone Programmierung in Node.js in einem Artikel
  • Detaillierte Erläuterung der Wissenspunkte zur asynchronen Programmierung in nodejs
  • Eine kurze Diskussion über die drei Hauptprobleme von JS: Asynchronität und Single-Thread

<<:  mysql5.7.18 dekomprimierte Version zum Starten des MySQL-Dienstes

>>:  Rsync+crontab regelmäßige Synchronisierungssicherung unter centos7

Artikel empfehlen

Grundlegende MySQL-Tabellenabfragen – häufige Fehler beim Left-Join

Überblick Bei kleinen und mittelgroßen Projekten ...

Eine kurze Erläuterung der HTML-Tabellen-Tags

Besprechen Sie hauptsächlich seine Struktur und ei...

Analyse und Lösung des a.getAttribute(href,2)-Problems in IE6/7

Kurzbeschreibung <br />In IE6 und 7 wird in...

MySQL wählt den passenden Datentyp für die ID

Inhaltsverzeichnis Zusammenfassung der Distribute...

Implementierungsprinzip und Skriptcode der HTML-Rabattpreisberechnung

Code kopieren Der Code lautet wie folgt: <!DOC...

Implementierungsbeispiel zum Schließen der Browserabmeldung in Vue

Inhaltsverzeichnis 1. beforeunload-Ereignis 2. Er...

Detaillierte Erklärung zu Unique Constraints und NULL in MySQL

Vorwort Eine Anforderung, die ich zuvor zur Verei...

Vue implementiert einen Countdown zwischen angegebenen Daten

In diesem Artikelbeispiel wird der spezifische Co...

Implementierung der schnellen Projektkonstruktion von vue3.0+vant3.0

Inhaltsverzeichnis 1. Projektkonstruktion 2. Vue3...