Node.js Promise-Tutorial

⚡ Intelligente Zusammenfassung

Promises in Node.js ersetzen tief verschachtelte Callbacks durch ein zurückgegebenes Objekt, das nur einmal festgelegt wird, sodass asynchrone Datenbankoperationen als eine flache Kette von then-Klauseln anstatt als eine Pyramide anonymer Funktionen gelesen werden können.

  • 🔘 Callback-Problem: Verschachtelte Rückruffunktionen werden lang und schwer zu pflegen.
  • ☑️ Grundlagen des Versprechens: Ein Promise gibt einen Wert zurück und wird genau einmal abgerechnet.
  • ✅ Verkettung: dann gibt die Funktion selbst ein Promise zurück, sodass die Einfügungen der Reihe nach ausgeführt werden.
  • 🧪 Individuelle Versprechen: Die q-Bibliothek denodeify umschließt jede Callback-Funktion.
  • ️ Moderne Form: async und await verbrauchen Promises ohne then-Callbacks.
  • 📊 Fehlerregel: Unbehandelte Fehler führen seit Version 15 zum Abbruch von Node.js.

Node.js Promise-Tutorial: Verkettung von Callbacks in Promises

In früheren Tutorials haben Sie Rückruffunktionen gesehen, die für asynchrone Ereignisse verwendet werden. Aber manchmal können Rückruffunktionen zu einem Albtraum werden, wenn sie verschachtelt werden und das Programm lang und komplex wird.

Was sind Versprechen?

Bevor wir uns mit Promises beschäftigen, wollen wir zunächst noch einmal klären, was „Callback“-Funktionen sind. Node.jsWir haben diese Callback-Funktionen in den vorangegangenen Kapiteln schon oft gesehen, also wollen wir uns kurz eine davon ansehen.

Das folgende Beispiel zeigt einen Codeausschnitt, der zum Herstellen einer Verbindung zu einem verwendet wird MongoDB Datenbank und führen Sie einen Aktualisierungsvorgang für einen der Datensätze in der Datenbank durch.

Node.js-Callback-Funktion, die eine Verbindung herstellt zu MongoDB und Aktualisierung eines Datensatzes

  1. Im obigen Code wird der Teil der Funktion (err,db) als Deklaration einer anonymen Funktion oder Rückruffunktion bezeichnet. Wenn der MongoClient eine Verbindung zum herstellt MongoDB Datenbank, wird es zur Rückruffunktion zurückkehren, sobald der Verbindungsvorgang abgeschlossen ist. In gewisser Weise finden die Verbindungsvorgänge also im Hintergrund statt, und wenn sie abgeschlossen sind, wird unsere Rückruffunktion aufgerufen. Denken Sie daran, dass dies einer der wichtigsten Punkte von Node.js ist, um viele Vorgänge gleichzeitig zu ermöglichen und somit keinen Benutzer daran zu hindern, einen Vorgang auszuführen.
  2. Der zweite Codeblock wird ausgeführt, wenn die Rückruffunktion tatsächlich aufgerufen wird. Die Rückruffunktion aktualisiert nur einen Datensatz in unserem MongoDB Datenbank.

Was ist dann ein Versprechen? Nun, ein Versprechen ist lediglich eine Erweiterung der Rückruffunktionen in Node.js. Während des Entwicklungslebenszyklus kann es vorkommen, dass Sie mehrere Rückruffunktionen verschachteln müssen. Dies kann zu einem bestimmten Zeitpunkt ziemlich chaotisch und schwierig zu verwalten sein. Kurz gesagt ist ein Versprechen eine Verbesserung von Rückrufen, die darauf abzielt, diese Probleme zu lindern.

Die grundlegende Syntax eines Versprechens ist unten dargestellt;

var promise = doSomethingAync()
promise.then(onFulfilled, onRejected)
  • „doSomethingAync“ ist eine beliebige Rückruf- oder asynchrone Funktion, die eine Art Verarbeitung durchführt.
  • Dieses Mal gibt es beim Definieren des Rückrufs einen zurückgegebenen Wert, der als „Versprechen“ bezeichnet wird.
  • Wenn ein Versprechen zurückgegeben wird, kann es zwei Ausgaben haben. Dies wird durch die „then-Klausel“ definiert. Entweder kann die Operation erfolgreich sein, was durch den Parameter „onFulfilled“ angezeigt wird. Oder es kann ein Fehler auftreten, was durch den Parameter „onRejected“ angezeigt wird.

A Versprechen sitzt in einem von drei Staaten und lässt sich nur einmal nieder:

Staat Bedeutung
Zu überprüfen Die Arbeiten sind noch nicht abgeschlossen.
Bestellung abgeschlossen onFulfilled wird mit dem Wert ausgeführt.
Abgelehnt onRejected wird mit dem Fehler ausgeführt.

Hinweis: Der Schlüsselaspekt eines Versprechens ist also der Rückgabewert. Beim Arbeiten mit normalen Rückrufen in Node.js gibt es kein Konzept für einen Rückgabewert. Aufgrund des Rückgabewerts haben wir mehr Kontrolle darüber, wie die Callback-Funktion definiert werden kann.

Versionshinweis: Diese Beispiele laufen noch unter Node.js 24, der aktiven LTS-Version ab 2026. Seit Node.js 15 und unbehandelte Ablehnung Beendet den Prozess, anstatt eine Warnung auszugeben. Schließe daher jede Kette mit .catch().

Im nächsten Thema sehen wir ein Beispiel für Versprechen und wie sie von Rückrufen profitieren.

Rückrufe auf Versprechen

Schauen wir uns nun ein Beispiel an, wie wir „Versprechen“ innerhalb einer Node.js-Anwendung verwenden können. Um Versprechen in einer Node.js-Anwendung verwenden zu können, muss zunächst das Modul „promise“ heruntergeladen und installiert werden.

Anschließend modifizieren wir unseren Code wie unten gezeigt. Dieser aktualisiert einen EmployeeName in der 'Employee'-Sammlung mithilfe von Promises.

Schritt 1) Installieren der NPM-Module

Um Promises in einer Node.js-Anwendung zu verwenden, wird das Promise-Modul benötigt. Um das Promise-Modul zu installieren, führen Sie den folgenden Befehl aus.

NPM-Installationsversprechen

Schritt 2) Ändern Sie den Code, um Versprechen einzuschließen

Screenshot des Editors, der das Promise-Modul beim Überschreiben zeigt. MongoDB Aktualisierung

var Promise = require('promise');
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost/EmployeeDB';

MongoClient.connect(url)
    .then(function(err, db) {
        db.collection('Employee').updateOne({
            "EmployeeName": "Martin"
        }, {
            $set: {
                "EmployeeName": "Mohan"
            }
        });
    }); 

Code Erläuterung:

  1. Der erste Teil besteht darin, das „Promise“-Modul einzubinden, das es uns ermöglicht, die Promise-Funktionalität in unserem Code zu verwenden.
  2. Wir können jetzt die Funktion „then“ an unsere Funktion „MongoClient.connect“ anhängen. Dies bedeutet also, dass wir beim Herstellen der Verbindung zur Datenbank das danach definierte Code-Snippet ausführen müssen.
  3. Schließlich definieren wir unser Code-Snippet, das den EmployeeName des Mitarbeiters mit dem Namen „Martin“ in „Mohan“ aktualisiert.

Hinweis:

Wenn Sie jetzt den Inhalt Ihres überprüfen MongoDB In der Datenbank werden Sie feststellen, dass ein Datensatz mit dem EmployeeName „Martin“ auf „Mohan“ aktualisiert wird.

Um zu überprüfen, ob die Daten richtig in die Datenbank eingefügt wurden, müssen Sie die folgenden Befehle ausführen in MongoDB

  1. Mitarbeiterdatenbank verwenden
  2. db.Employee.find({EmployeeName : “Mohan”})

Die erste Anweisung stellt sicher, dass Sie mit der EmployeeDB-Datenbank verbunden sind. Die zweite Anweisung sucht nach dem Datensatz mit dem Mitarbeiternamen „Mohan“.

Umgang mit verschachtelten Versprechen

Bei der Definition von Versprechen ist zu beachten, dass die „thann“-Methode selbst ein Versprechen zurückgibt. In gewissem Sinne können Versprechen verschachtelt oder miteinander verkettet werden.

Im folgenden Beispiel verwenden wir die Verkettung, um zwei Rückruffunktionen zu definieren, die beide einen Datensatz in die einfügen MongoDB Datenbank.

(Hinweis: Verkettung ist ein Konzept, mit dem die Ausführung von Methoden miteinander verknüpft wird. Angenommen, Ihre Anwendung verfügt über zwei Methoden namens „MethodeA“ und „MethodeB“. Und die Logik war so, dass „MethodeB“ nach „MethodeA“ aufgerufen werden sollte, dann würden Sie die Ausführung so verketten, dass „MethodeB“ direkt nach „MethodeA“ aufgerufen wird.)

Der entscheidende Punkt in diesem Beispiel ist, dass der Code durch die Verwendung verschachtelter Promises sauberer, lesbarer und wartbarer wird.

Verkettete dann-Klauseln, die zwei Mitarbeiterdatensätze einfügen in MongoDB

var Promise = require('promise');
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost/EmployeeDB';
MongoClient.connect(url)

.then(function(db) {
    db.collection('Employee').insertOne({
        Employeeid: 4,
        EmployeeName: "NewEmployee"
    })

    .then(function(db1) {
        db1.collection('Employee').insertOne({
            Employeeid: 5,
            EmployeeName: "NewEmployee1"
        })
    })
});

Code Erläuterung:

  1. Wir definieren jetzt zwei „Dann“-Klauseln, die nacheinander ausgeführt werden. In der ersten then-Klausel übergeben wir den Parameter „db“, der unsere Datenbankverbindung enthält. Anschließend verwenden wir die Sammlungseigenschaft der „db“-Verbindung, um Datensätze in die „Employee“-Sammlung einzufügen. Mit der Methode „insertOne“ wird das eigentliche Dokument in die Employee-Sammlung eingefügt.
  2. Wir verwenden dann die 2nd then-Klausel auch zum Einfügen eines weiteren Datensatzes in die Datenbank.

Wenn Sie jetzt den Inhalt Ihres überprüfen MongoDB In der Datenbank finden Sie die beiden eingefügten Datensätze. MongoDB Datenbank.

Modernes Äquivalent: async und await, Standard seit ES2017, verarbeiten diese Promises ohne then-Callbacks und haben sie weitgehend ersetzt. generatorbasiert Ablaufsteuerungsbibliotheken wie co werden durch die native Promise-Unterstützung ersetzt, wodurch q und bluebird überflüssig werden. Der zweite Block zeigt dann, wie nur db empfangen wird.

Erstellen Sie ein individuelles Versprechen

Benutzerdefinierte Promises lassen sich mithilfe des Node.js-Moduls „q“ erstellen. Die „q“-Bibliothek muss über den Node Package Manager heruntergeladen und installiert werden. Nach der Verwendung der „q“-Bibliothek kann die Methode „denodeify“ aufgerufen werden, die jede Funktion in eine Funktion umwandelt, die ein Promise zurückgibt.

Im folgenden Beispiel erstellen wir eine einfache Funktion namens „Add“, die zwei Zahlen addiert. Wir konvertieren diese Funktion in eine Funktion, die ein Versprechen zurückgibt.

Sobald dies erledigt ist, verwenden wir das von der Add-Funktion zurückgegebene Versprechen, um eine Nachricht im console.log anzuzeigen.

Befolgen Sie die folgenden Schritte, um unsere benutzerdefinierte Funktion zur Rückgabe eines Versprechens zu erstellen.

Schritt 1) Installieren der NPM-Module

Um 'q' in einer Node.js-Anwendung zu verwenden, wird das 'q'-Modul benötigt. Um das 'q'-Modul zu installieren, führen Sie den folgenden Befehl aus.

npm install q

Schritt 2) Definieren Sie den folgenden Code, der zum Erstellen des benutzerdefinierten Versprechens verwendet wird.

Individuelles Versprechen erstellt von wrapping eine Add-Funktion mit q denodeify

Code Erläuterung:

  1. Das erste Bit besteht darin, die Bibliothek „q“ mithilfe des Schlüsselworts require einzubinden. Durch die Verwendung dieser Bibliothek können wir jede Funktion definieren, die einen Rückruf zurückgibt.
  2. Wir erstellen eine Funktion namens Add, die zwei in den Variablen a und b definierte Zahlen addiert. Die Summe dieser Werte wird in der Variable c gespeichert.
  3. Anschließend verwenden wir die q-Bibliothek, um unsere Add-Funktion zu denodeifizieren (die Methode, mit der jede Funktion in eine Funktion umgewandelt wird, die ein Promise zurückgibt), oder mit anderen Worten, um unsere Add-Funktion in eine Funktion umzuwandeln, die ein Promise zurückgibt.
  4. Wir rufen jetzt unsere „Add“-Funktion auf und können aufgrund des vorherigen Schrittes, den wir durchgeführt haben, um die Add-Funktion zu entodeifizieren, einen Return-Promise-Wert erhalten.
  5. Das Schlüsselwort 'then' wird verwendet, um anzugeben, dass im Falle einer erfolgreichen Ausführung der Funktion die Zeichenkette „Addition function completed“ in console.log angezeigt werden soll.

Wenn der obige Code ausgeführt wird, wird die Ausgabe „Additionsfunktion abgeschlossen“ wie unten gezeigt im console.log angezeigt.

Konsolenausgabe: Additionsfunktion aus dem benutzerdefinierten Versprechen abgeschlossen

Häufig gestellte Fragen

Seit Node.js 15 beendet sich der Prozess mit einem Fehlercode ungleich Null anstatt mit einer Warnung. Fügen Sie .catch() an jede Kette an oder registrieren Sie einen Prozessbehandler zum Protokollieren und Wiederherstellen.

.catch() fängt jeden Fehler ab, der zuvor in der Kette aufgetreten ist, ähnlich wie ein try-Block. .finally() wird unabhängig vom Ergebnis der Kette ausgeführt und eignet sich daher zum Schließen einer Verbindung.

Promise.all schlägt sofort fehl, wenn eine Eingabe abgelehnt wird. allSettled löst immer alle Ergebnisse aus und gibt sie aus. race verwendet das erste gelöste Ergebnis. any benötigt mindestens einen Erfolg, andernfalls wird AggregateError ausgelöst.

Beide verwenden dasselbe Promise. `await` pausiert innerhalb einer asynchronen Funktion, sodass Ergebnisse in normalen Variablen landen und Fehler einen try-catch-Block erreichen.

Selten. Generator Funktionen mit yield waren einst der Antrieb für Bibliotheken wie co, aber async und await decken diese Aufgabe nativ ab. Generators eignen sich immer noch für Lazy Sequences und benutzerdefinierte Iteratoren.

util.promisify konvertiert eine Callback-Funktion direkt, und Module wie fs.promises liefern bereits Promises zurück. Beide ersetzen die oben gezeigte q-Bibliothek.

Ja. Maschinell lernende Analysetools kennzeichnen Verarbeitungsketten ohne Fehlerbehandlung, mit Wartezeiten innerhalb von Schleifen und mit reihenfolgeabhängigen Schreibvorgängen und ordnen die Ergebnisse anschließend nach ihrer Reihenfolge. Tests Begeben Sie sich auf die riskantesten Wege.

GitHub-Copilot und ähnliche agentenbasierte Assistenten schreiben verschachtelte Rückrufe schnell in await-Aufrufe um, doch jede Umschreibung muss überprüft werden, da Fehlerpfade und Route Semantik verschiebt sich stillschweigend.

Fassen Sie diesen Beitrag mit folgenden Worten zusammen: