Inhaltsverzeichnis Einführung Synchron Asynchron und Blockierend Nicht blockierend Callbacks in JavaScript Fehlerbehandlung von Callback-Funktionen Callback-Hölle Promise in ES6 Was ist Promise? Funktionen von Promise Vorteile von Promise Nachteile von Promise Verwendung von Promise Ausführungsreihenfolge von Promise Ausführungsreihenfolge von async und await async Zusammenfassung der Funktionen von async EinführungWeil 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 blockierendBevor 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 JavascriptCallbacks 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-FunktionenWie 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ölleObwohl 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 ES6Was 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 PromisePromise hat zwei Eigenschaften: 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. Sobald sich der Status ändert, ändert er sich nicht mehr und das 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 PromisesPromise drückt asynchrone Operationen in Form von synchronen Operationen aus und vermeidet verschachtelte Rückruffunktionen. Das Promise-Objekt bietet eine einheitliche Schnittstelle, die die Steuerung asynchroner Vorgänge erleichtert. Nachteile von Promises
Verwendung von PromisesDas 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ührungSobald 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 wartenVersprechen 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ührungsreihenfolgeAwait 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:
Wie Sie sehen, wird aysnc asynchron ausgeführt und seine Sequenz folgt dem aktuellen Zyklus. Funktionen von asyncAsync 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) ZusammenfassenPromise 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 über ein vertieftes Verständnis der asynchronen Programmierung in nodejs. Weitere relevante Inhalte zur asynchronen Programmierung in nodejs finden Sie in früheren Artikeln auf 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:
|
>>: 10 beliebte Windows-Apps, die auch unter Linux verfügbar sind
Ich habe gerade angefangen, Datenbankoperationen ...
Verwenden Sie hauptsächlich die Eigenschaften „pr...
Vorwort Jede gute Angewohnheit ist ein Schatz. Di...
Beim Rendern von Markdown habe ich zuvor den Vors...
IE8 wird mehrere Kompatibilitätsmodi haben. Der IE...
In diesem Artikel erfahren Sie den spezifischen J...
Detaillierte Erläuterung des Konfigurationsprozes...
Inhaltsverzeichnis Die Reihenfolge, in der MySQL ...
Finden Sie zunächst heraus, wo sich die Konfigura...
In diesem Artikel wird der spezifische Code von R...
/***************** * proc-Dateisystem************...
Während des Crawler-Entwicklungsprozesses sind Si...
Vorwort Durch das Erstellen von Verknüpfungen in ...
Hintergrund Während des Projektentwicklungsprozes...
Die folgende Abbildung zeigt die Browser-Anzeiger...