Detaillierte Erläuterung der Wissenspunkte zur asynchronen Programmierung in nodejs

Detaillierte Erläuterung der Wissenspunkte zur asynchronen Programmierung in nodejs

Einführung

Weil JavaScript standardmäßig ein Thread ist, was bedeutet, dass der Code keine neuen Threads erstellen kann, um sie parallel auszuführen. Für das JavaScript, das zuerst im Browser ausgeführt wurde, konnte die Umgebung für die synchrone Ausführung mit einem Thread die Anforderungen benutzerreaktiver Funktionen wie Seitenklicks und Mausbewegungen offensichtlich nicht erfüllen. Der Browser hat daher eine Reihe von APIs implementiert, die es JavaScript ermöglichen, im Callback-Verfahren asynchron auf Seitenanforderungsereignisse zu reagieren.

Darüber hinaus führte NodeJS nicht blockierende E/A ein und erweiterte so das Konzept der Asynchronität auf Dateizugriffe, Netzwerkaufrufe usw.

Heute werden wir einen detaillierten Blick auf die Vor- und Nachteile sowie die Entwicklungstrends verschiedener asynchroner Programmierungen werfen.

Synchron, asynchron, blockierend, nicht blockierend

Bevor wir die asynchrone Programmierung von node.js besprechen, besprechen wir ein Konzept, das leichter zu verwechseln ist, nämlich synchron, asynchron, blockierend und nicht blockierend.

Das sogenannte Blockieren und Nichtblockieren bezieht sich darauf, ob ein Prozess oder Thread beim Ausführen von Vorgängen oder beim Lesen und Schreiben von Daten warten muss und ob während des Wartevorgangs andere Vorgänge ausgeführt werden können.

Wenn ein Warten erforderlich ist und der Thread oder Prozess während des Wartevorgangs keine anderen Vorgänge ausführen kann und nur dumm warten kann, dann sagen wir, dass dieser Vorgang blockiert ist.

Im Gegenteil: Wenn ein Prozess oder Thread während der Ausführung einer Operation oder beim Lesen und Schreiben von Daten andere Operationen ausführen kann, dann bezeichnen wir die Operation als nicht blockierend.

Synchron und asynchron beziehen sich auf die Art des Datenzugriffs. Synchron bedeutet, dass Daten aktiv gelesen werden müssen und dieser Lesevorgang blockierend oder nicht blockierend sein kann. Asynchron bedeutet, dass kein aktives Auslesen der Daten notwendig ist, es handelt sich um eine passive Benachrichtigung.

Offensichtlich ist der Rückruf in JavaScript eine passive Benachrichtigung, die wir einen asynchronen Aufruf nennen können.

Rückrufe in Javascript

Callbacks in JavaScript sind ein sehr typisches Beispiel für asynchrone Programmierung:

document.getElementById('button').addEventListener('click', () => {
 console.log('Schaltfläche angeklickt!');
})

Im obigen Code haben wir der Schaltfläche einen Klickereignis-Listener hinzugefügt. Wenn ein Klickereignis abgehört wird, wird die Rückruffunktion ausgelöst, um die entsprechenden Informationen auszugeben.

Die Rückruffunktion ist eine normale Funktion, mit dem Unterschied, dass sie als Parameter an addEventListener übergeben wird und nur aufgerufen wird, wenn das Ereignis ausgelöst wird.

Die setTimeout- und setInterval-Funktionen, über die wir im vorherigen Artikel gesprochen haben, sind eigentlich asynchrone Rückruffunktionen.

Fehlerbehandlung in Callback-Funktionen

Wie gehe ich mit Rückruffehlerinformationen in Node.js um? Nodejs verwendet eine sehr clevere Methode. In Nodejs ist der erste Parameter in jeder Rückruffunktion das Fehlerobjekt. Wir können eine entsprechende Fehlerbehandlung durchführen, indem wir beurteilen, ob dieses Fehlerobjekt existiert oder nicht.

fs.readFile('/Datei.json', (err, data) => {
 wenn (err !== null) {
 //Fehler behandeln console.log(err)
 zurückkehren
 }

 // Wenn kein Fehler vorliegt, verarbeite die Daten.
 console.log(Daten)
})

Rückruf Hölle

Obwohl JavaScript-Rückrufe hervorragend sind, lösen sie effektiv das Problem der synchronen Verarbeitung. Wenn wir uns jedoch zum Ausführen des nächsten Schritts auf den Rückgabewert der Rückruffunktion verlassen müssen, geraten wir leider in diese Rückrufhölle.

Es als Callback-Hölle zu bezeichnen ist zwar etwas übertrieben, spiegelt aber auch die Probleme von Callback-Funktionen aus einer Perspektive wider.

fs.readFile('/a.json', (err, data) => {
 wenn (err !== null) {
 fs.readFile('/b.json',(err,data) => {
  //Rückruf innerhalb des Rückrufs
 })
 }
})

Wie kann man das Problem lösen?

Keine Angst, ES6 hat Promise und ES2017 Async/Await eingeführt, was dieses Problem lösen kann.

Versprechen in ES6

Was ist ein Versprechen?

Promise ist eine Lösung für asynchrone Programmierung, die sinnvoller und leistungsfähiger ist als die herkömmliche Lösung von „Rückruffunktionen und Ereignissen“.

Das sogenannte Promise ist einfach ein Container, der das Ergebnis eines Ereignisses speichert, das in der Zukunft endet (normalerweise eine asynchrone Operation).

Syntaktisch gesehen ist ein Promise ein Objekt, von dem Sie Nachrichten über asynchrone Vorgänge erhalten können.

Funktionen von Promise

Promise hat zwei Eigenschaften:

1. Der Zustand des Objekts wird nicht von der Außenwelt beeinflusst.

Das Promise-Objekt stellt eine asynchrone Operation dar und hat drei Zustände: Ausstehend (in Bearbeitung), Gelöst (abgeschlossen, auch als Erfüllt bekannt) und Abgelehnt (fehlgeschlagen).

Nur das Ergebnis der asynchronen Operation kann den aktuellen Status bestimmen, und keine andere Operation kann diesen Status ändern.

2. Sobald sich der Status ändert, ändert er sich nicht erneut und dieses Ergebnis kann jederzeit abgerufen werden.

Es gibt nur zwei Möglichkeiten, den Status eines Promise-Objekts zu ändern: von „Ausstehend“ zu „Gelöst“ und von „Ausstehend“ zu „Abgelehnt“.

Dies ist etwas völlig anderes als ein Ereignis. Das Merkmal eines Ereignisses besteht darin, dass Sie keine Ergebnisse erzielen, wenn Sie es verpassen und dann darauf hören.

Vorteile von Promises

  1. Promise drückt asynchrone Operationen in Form von synchronen Operationen aus und vermeidet verschachtelte Rückruffunktionen.
  2. Das Promise-Objekt bietet eine einheitliche Schnittstelle, die die Steuerung asynchroner Vorgänge erleichtert.

Nachteile von Promises

  1. Das Versprechen kann nicht storniert werden. Sobald es erstellt wurde, wird es sofort ausgeführt und kann nicht auf halbem Weg storniert werden.
  2. Wenn die Rückruffunktion nicht festgelegt ist, wird der in Promise ausgelöste Fehler nicht extern angezeigt.
  3. Im Status „Ausstehend“ können Sie nicht wissen, in welchem ​​Stadium sich das Projekt derzeit befindet (gerade begonnen oder kurz vor dem Abschluss).

Verwendung von Promises

Das Promise-Objekt ist ein Konstruktor, der eine Promise-Instanz generiert:

var promise = neues Versprechen(Funktion(auflösen, ablehnen) { 
// ... etwas Code 
if (/* asynchroner Vorgang erfolgreich*/){ 
Auflösung (Wert); 
} sonst { ablehnen(Fehler); } 
}
);

Promise kann mit der then-Operation verbunden werden, und die then-Operation kann mit zwei Funktionsparametern verbunden werden. Der erste Funktionsparameter ist der aufgelöste Wert beim Erstellen des Promise und der zweite Funktionsparameter ist der Fehler bei der Ablehnung des Promise.

Versprechen.dann(Funktion(Wert) { 
// Erfolg 
}, Funktion(Fehler) { 
// Versagen }
);

Schauen wir uns ein konkretes Beispiel an:

Funktion Timeout (ms) {
 returniere neues Promise(((lösen, ablehnen) => {
  setTimeout(auflösen, ms, „erledigt“);
 }))
}

Timeout (100).dann (Wert => Konsole.log (Wert));

In Promise wird eine setTimeout-Methode aufgerufen, die zu einem festgelegten Zeitpunkt die Resolve-Methode auslöst und den Parameter done übergibt.

Schließlich gibt das Programm fertig aus.

Reihenfolge der Versprechensausführung

Sobald ein Promise erstellt wurde, wird es sofort ausgeführt. Die Methode in Promise.then wartet jedoch, bis ein Aufrufzyklus abgelaufen ist, bevor sie erneut aufruft. Sehen wir uns das folgende Beispiel an:

let promise = neues Versprechen(((lösen, ablehnen) => {
 console.log('Schritt1');
 lösen();
}));

versprechen.dann(() => {
 console.log('Schritt3');
});

console.log('Schritt2');

Ausgabe

Schritt 1
Schritt 2
Schritt 3

asynchron und warten

Versprechen sind großartig, natürlich wandeln wir die Callback-Hölle in Kettenaufrufe um. Wir verwenden „then“, um mehrere Promises zu verbinden, und das Ergebnis der Auflösung des vorherigen Promises ist der Parameter von „then“ im nächsten Promise.

Welche Nachteile haben Kettenanrufe?

Wenn wir beispielsweise einen Wert aus einem Versprechen auflösen, müssen wir basierend auf diesem Wert einige Geschäftslogikverarbeitungen durchführen.

Wenn diese Geschäftslogik sehr lang ist, müssen wir im nächsten Schritt einen langen Geschäftslogikcode schreiben. Dadurch erscheint unser Code sehr redundant.

Gibt es also eine Möglichkeit, das Ergebnis der Lösung direkt im Versprechen zurückzugeben?

Die Antwort ist: abwarten.

Wenn einem Versprechen ein „Warten“ vorangestellt ist, wird der aufrufende Code angehalten, bis das Versprechen eingelöst oder abgelehnt wird.

Beachten Sie, dass „await“ in einer asynchronen Funktion platziert werden muss. Sehen wir uns ein Beispiel für „async“ und „await“ an:

const logAsync = () => {
 gib ein neues Versprechen zurück (Auflösen => {
 setTimeout(() => lösen('Xiao Ma Ge'), 5000)
 })
}

Oben haben wir eine logAsync-Funktion definiert, die ein Promise zurückgibt. Da das Promise zur Auflösung setTimeout verwendet, können wir es als asynchron betrachten.

Um „await“ zum Abrufen des Resolve-Werts zu verwenden, müssen wir ihn in eine asynchrone Funktion einfügen:

const doSomething = async () => {
 const resolveValue = warte auf logAsync();
 console.log(Wert auflösen);
}

Asynchrone Ausführungsreihenfolge

Await wartet tatsächlich auf das Auflösungsergebnis des Versprechens. Kombinieren wir die obigen Beispiele:

const logAsync = () => {
 gib ein neues Versprechen zurück (Auflösen => {
  setTimeout(() => lösen('Xiao Ma Ge'), 1000)
 })
}

const doSomething = async () => {
 const resolveValue = warte auf logAsync();
 console.log(Wert auflösen);
}

console.log('vorher')
tuEtwas();
console.log('nach')

Das obige Beispiel gibt Folgendes aus:

vor
nach
Kleine Mama

Wie Sie sehen, wird aysnc asynchron ausgeführt und seine Sequenz folgt dem aktuellen Zyklus.

Funktionen von async

Async wandelt alle nachfolgenden Funktionen in Promises um, auch wenn die nachfolgenden Funktionen nicht explizit Promises zurückgeben.

const asyncReturn = async () => {
 returniere 'asynchrone Rückgabe'
}

asyncReturn().then(Konsole.log)

Da bis dahin nur Promise befolgt werden kann, können wir sehen, dass async eine normale Funktion in ein Promise kapselt:

const asyncReturn = async () => {
 returniere Promise.resolve('asynchrone Rückgabe')
}

asyncReturn().then(Konsole.log)

Zusammenfassen

Promise vermeidet die Callback-Hölle, indem es den Callback innerhalb des Callbacks in einen Kettenaufruf von then umschreibt.

Kettenaufrufe sind jedoch zum Lesen und Debuggen nicht praktisch. So erschienen async und await.

Asynchrone und wartende Aufrufe ändern die Kettenaufrufe in eine Syntax, die der sequentiellen Ausführung von Programmen ähnelt, wodurch sie leichter zu verstehen und zu debuggen sind.

Schauen wir uns einen Vergleich an und betrachten zunächst die Verwendung von Promise:

const getUserInfo = () => {
 return fetch('/users.json') // Benutzerliste abrufen.then(response => response.json()) // JSON analysieren
 .then(users => users[0]) // Den ersten Benutzer auswählen.then(user => fetch(`/users/${user.name}`)) // Benutzerdaten abrufen.then(userResponse => userResponse.json()) // JSON analysieren
}

getUserInfo()

Schreiben Sie es mit async neu und warten Sie:

const getUserInfo = async () => {
 const response = await fetch('/users.json') // Benutzerliste abrufen const users = await response.json() // JSON analysieren
 const user = users[0] // Ersten Benutzer auswählen const userResponse = await fetch(`/users/${user.name}`) // Benutzerdaten abrufen const userData = await userResponse.json() // JSON analysieren
 Benutzerdaten zurückgeben
}

getUserInfo()

Sie sehen, dass die Geschäftslogik klarer wird. Gleichzeitig erhalten wir viele Zwischenwerte, was uns das Debuggen erleichtert.

Dies ist das Ende dieses Artikels mit der detaillierten Erklärung der Wissenspunkte zur asynchronen Programmierung in nodejs. Für ein relevanteres und tieferes Verständnis der asynchronen Programmierung in nodejs suchen Sie bitte nach früheren Artikeln auf 123WORDPRESS.COM oder durchsuchen Sie weiterhin die folgenden verwandten Artikel. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

Das könnte Sie auch interessieren:
  • Detaillierte Erklärung der in JS integrierten Objekte und mathematischen Objekte
  • Detaillierte Erläuterung der Wissenspunkte von VsCode und Node.js
  • Detaillierte Erläuterung der Verbindung von NodeJS mit der MySQL-Datenbank und grundlegender Wissenspunkte
  • Detaillierte Erläuterung des Foto-Wasserfalleffekts (JS, JQuery-Implementierung und Zusammenfassung der Wissenspunkte)
  • Zusammenfassung der JavaScript-Wissenspunkte (XVI) Detaillierte Erläuterung des Javascript-Closure-Codes
  • Zusammenfassung der JavaScript-Wissenspunkte (XI) Detaillierte Erläuterung der Object-Klasse in js
  • Zusammenfassung der JavaScript-Wissenspunkte (IV) Detaillierte Erläuterung des logischen ODER-Operators
  • Detaillierte Erläuterung der Javascript-Wissenspunkte

<<:  Detaillierte Erklärung, wie Angular mit unerwarteten Ausnahmefehlern umgeht

>>:  js Addition, Subtraktion, Multiplikation und Division – Beispielcode für präzise Berechnungsmethoden

Artikel empfehlen

ReactHooks Batch-Update-Status und Abrufen von Routenparametern Beispielanalyse

Inhaltsverzeichnis 1. So führen Sie stapelweise U...

So erstellen Sie einen Trigger in MySQL

In diesem Artikelbeispiel wird der spezifische Co...

Eine kurze Analyse von Kubernetes-Controllern und -Labels

Inhaltsverzeichnis 01 Gemeinsame Controller in k8...

Drei Möglichkeiten zum Aktualisieren von Iframes

Code kopieren Der Code lautet wie folgt: <ifra...

Reines CSS3 zum Erstellen eines Beispielcodes für Haushühner

Ich habe in letzter Zeit viel Wissen und Artikel ...

So fügen Sie ein Lua-Modul zu Nginx hinzu

Lua installieren wget http://luajit.org/download/...

Vue3 Vue-Ereignisbehandlungshandbuch

Inhaltsverzeichnis 1. Grundlegende Ereignisbehand...

Importieren von CSS-Dateien unter Verwendung von Beurteilungsbedingungen

Lösung 1: Verwenden Sie bedingten Import im HTML-...

Es ist ganz einfach zu verstehen, was Node.js ist

Inhaltsverzeichnis Offizielle Einführung in Node....