Asynchrone Abfragen mit Node.js und Async.js

Angenommen man möchte drei Datenbank-Abfragen durchführen. In einer synchronen Scriptsprache wie z.B. PHP würde man dafür einfach die entsprechende Datenbank-Funktion aufrufen, und das Ergebnis in einer Variable speichern. Das sehe dann wie folgt aus (Pseudocode):

$eins = abfrage('eins');
$zwei = abfrage('zwei');
$drei = abfrage('drei');


Eine asynchrone Scriptsprache läuft hingegen nicht strikt von oben nach unten ab. Dies hat den Vorteil, dass eine Datenbankabfrage nicht den Programm-Ablauf anhält, sondern stattdessen andere Bereiche des Scriptes erledigt werden.

Eine asynchrone Funktion liefert im Gegensatz zu einer synchronen Funktion die Ergebnisse nicht direkt als Rückgabewert zurück, sondern nimmt als Parameter eine Rückruf-Funktion (englisch callback) entgegen, an welche der Rückgabewert dann als Parameter übergeben wird.

JavaScript (und somit auch die Node.js-Plattform) zählt zu diesen asynchronen Scriptsprachen. Die gleiche Abfrage mit JavaScript bzw. Node.js sehe folgendermaßen aus:

abfrage('eins', function(ergebnisEins){
    abfrage('zwei', function(ergebnisZwei){
        abfrage('drei', function(ergebnisDrei){
            console.log('Eins: ' + ergebnisEins + ' Zwei: ' + ergebnisZwei + ' Drei: ' + ergebnisDrei);
        });
    });
});

Hier würde zuerst Abfrage-Eins durchgeführt, sobald diese abgeschlossen ist Abfrage-Zwei und danach Abfrage-Drei. Abschließend würden die drei Ergebnisse zusammen in die Konsole geschrieben.

Async.js #

Da das Ineinanderverschachteln von Abfragen schnell unübersichtlich werden kann, empfiehlt es sich, das Node.js-Modul async zu verwenden. Mit NPM installiert man async über folgende Konsolen-Anweisung:

npm install async

Danach kann man es in in eine Node.js-Anwendung laden, dies geschieht mit:

var async = require('async');

Die gleichen drei Abfragen mit async würden dann wie folgt aussehen:

async.series({
    eins: function(callback){
        abfrage('eins', function(ergebnis){
            callback(null, ergebnis);
        });
    },
    zwei: function(callback){
        abfrage('zwei', function(ergebnis){
            callback(null, ergebnis);
        });
    },
    drei: function(callback){
        abfrage('drei', function(ergebnis){
            callback(null, ergebnis);
        });
    }
}, function(err, ergebnis){
    console.log('Eins: ' + ergebnis.eins + ' Zwei: ' + ergebnis.zwei + ' Drei: ' + ergebnis.drei);
});

Mit async.series werden die übergebenen Funktionen nacheinander ausgeführt. Als ersten Parameter erwartet async.series ein Array oder ein Objekt mit den auszuführenden Funktionen. Jede einzelne dieser Funktionen nimmt als ersten Parameter eine Callback-Funktion entgegen, die dann aufgerufen wird, wenn diese Funktion abgeschlossen ist. Dabei erwartet die Callback-Funktion als ersten Parameter einen möglicherweise aufgetretenen Fehler (falls kein Fehler vorhandne ist null), sowie als zweiten Parameter das Ergebnis dieser Abfrage.

Als zweiten Parameter erwartet async.series die Rückruf-Funktion, die nach Abschluss aller Funktionen aufgerufen wird. Sie erwartet wiederum als ersten Parameter den aufgetretenen Fehler (falls vorhanden), sowie als zweiten Parameter ein Array bzw. ein Objekt mit den Ergebnissen alle aufgerufenen Funktionen.

Parallele Abfragen #

Falls die Abfragen hingegen nicht nacheinander, sondern parallel zueinander aufgerufen werden sollen, so kann man async.parallel anstelle von async.series verwenden. Die erwarteten Parameter sind dabei identisch.

Der große Vorteil von parallelen Datenbankabfragen ist, dass man schneller zum Endergebnis kommt, da alle Abfragen sofort abgesendet werden, nicht erst gewartet wird, bis die jeweils vorherige Abfrage beantwortet wurde.

async.parallel({
    eins: function(callback){
        abfrage('eins', function(ergebnis){
            callback(null, ergebnis);
        });
    },
    zwei: function(callback){
        abfrage('zwei', function(ergebnis){
            callback(null, ergebnis);
        });
    },
    drei: function(callback){
        abfrage('drei', function(ergebnis){
            callback(null, ergebnis);
        });
    }
}, function(err, ergebnis){
    console.log('Eins: ' + ergebnis.eins + ' Zwei: ' + ergebnis.zwei + ' Drei: ' + ergebnis.drei);
});

Parallele Abfragen können jedoch nicht verwendet werden, wenn zwei Abfragen aufeinander aufbauen. In solchen Fällen müssen Datenbankabfragen selbstverständlich weiterhin nacheinander mit async.series getätigt werden.

Neben dem hier vorgestellten Szenario von asynchronen Abfragen beherrscht async noch eine Menge weiterer hilfreicher Funktionen, die ebenfalls lesbareren und performanteren Programmcode ermöglichen. Zudem kann man Async.js auch im Webbrowser verwenden, mehr dazu findet sich im GitHub-Repository von Async.js.

VN:F [1.9.22_1171]
Bewertung: 4.8/5 (6 Bewertungen)
Asynchrone Abfragen mit Node.js und Async.js, 4.8 out of 5 based on 6 ratings
Regelmäßige Beiträge über Node.js

nodecodeAbonniere den kostenlosen NodeCode-Newsletter, und bleibe auf dem laufenden über neue Beiträge zum Thema Node.js. Darunter:

  • Informationen und Neuigkeiten rund um Node.js und zugehörigen Modulen
  • Vorstellung von interessanten Frameworks und Bibliotheken
  • Anleitungen und Tutorials zu Node.js und weiterführenden Technologien
  • Sowie vieles mehr...

schon 9 Kommentare gehe zum kommentieren

  1. Dan /

    Gute Einführung in die Thematik, danke!

  2. Werner Schäffer /

    In den Code-Beispielen fehlt jeweils vor dem letzten Semikolon eine abschließende runde Klammer.

    1. NodeCode / Beitrags-Autor

      Stimmt, die abschließenden Klammern wurden in den beiden Beispielen vergessen. Wurde soeben korrigiert.

  3. Alex Jank /

    Eine Frage, die ich mir doch stelle ist, ob es in Node.js auch so etwas wie Promises gibt? – Dies würde solche asynchronen Abfragen noch besser les- bzw. schreibbar machen.

    1. NodeCode / Beitrags-Autor

      Ja, dafür gibt es die beiden Node.js-Module q und promise.

  4. video background website /

    Was ist der Unterschied von async.parallel und async.linear ?

    1. NodeCode / Beitrags-Autor

      async.parallel führt die Aufgaben parallel zueinander aus, die Funktion async.linear gibt es hingegen nicht. Du meinst wahrscheinlich stattdessen die Funktion async.series, diese führt die Aufgaben nacheinander aus, macht bei der nächsten also erst dann weiter, wenn die vorhergehende Aufgabe abgeschlossen ist.

      Übrigens, Keywords als Namen bei einem Kommentar zu verwenden, dazu einen entsprechenden Link als Website zu setzen und eine scheinbar erfundene Email-Adresse zu verwenden (obwohl die Angabe einer Email-Adresse nur optional ist) sieht verdächtig nach Kommentar-Spam aus. Hättest du keinen einigermaßen sinnvollen Kommentar geschrieben, wäre dein Kommentar im Spamordner gelandet. Falls du Backlinks aufbauen möchtest bist du hier falsch, da alle Kommentar-Links mit rel="nofollow" versehen werden, und somit keinen Vorteil beim Google-Ranking bieten. 😉

      1. nofollow /

        rel=“nofollow“ hilft das auch heute noch?

        1. NodeCode / Beitrags-Autor

          Ja, laut Aussagen von Google:

          Wie behandelt Google mit „nofollow“ gekennzeichnete Links?

          Im Allgemeinen folgen wir diesen nicht. Das bedeutet, dass von Google über diese Links kein PageRank und kein Ankertext übermittelt wird. Bei Verwendung von nofollow werden die Ziellinks also nicht für unsere Gesamtdarstellung des Webs berücksichtigt. […]

          Siehe: https://support.google.com/webmasters/answer/96569?hl=de

hinterlasse einen Kommentar