15 Stimmen

JavaScript-Entwurfsmuster -- Umgang mit unerwünschter Asynchronität

Ich bin ziemlich neu in der ereignisbasierten Programmierung (mit node.js). Ich glaube, dass es etwas gibt, das ich einfach nicht begreife, weil ich immer wieder auf ein bestimmtes Problem stoße.

Kurz gesagt besteht das Problem darin, mit Asynchronität umzugehen, wenn es einem im Weg zu stehen scheint. Dies zeigt sich bei mir am häufigsten, wenn ich mit Drittanbieter-Bibliotheken arbeite, die von Natur aus nicht blockierend sind und eine rückrufbasierte API fördern.

Zum Beispiel: Im Moment schreibe ich etwas, das intensiv die Mranneys node-redis Bibliothek nutzt. Mein Programm liest RSS-Feeds aus und speichert die Ergebnisse in Redis. Ich verwende dabei eine Strategie, die ich für gängig halte:

  1. Feed scannen, Ergebnisse als Redis-Hash mit einem Schlüssel wie feed::results: speichern.
  2. Referenz zum neuesten Ergebnis unter feed::latest speichern.

    var redis = require("redis"); var client = redis.createClient();

    var get_latest_results = function (feedId) { client.get('feed:+ feedId + ':latest', function (err, res) { var latest_reading_key = res.toString(); client.hgetall(latest_reading_key, function (err, res) { var latest_reading = res; }); }); // wie kann ich einen Rückgabewert für diese Funktion festlegen? }

Das Platzieren von return latest_reading am Ende der Funktion get_latest_results schlägt fehl, da latest_reading erst nach dem Verlassen der Funktion definiert ist. Das Platzieren von return latest_reading innerhalb des hgetall-Aufrufs schlägt fehl, weil das return auf den Rückruf verweist und von get_latest_results ignoriert wird.

Dies ist nur ein Beispiel für die Art von Situation, in die ich anscheinend ständig gerate. Vielleicht versuche ich das Unmögliche zu erreichen, weil ich es nicht besser weiß. Es scheint, dass es einen nicht-hackischen Weg geben sollte, um diese Art von Problemen zu lösen.

28voto

Daniel Vassallo Punkte 325264

Sie haben Probleme mit der Asynchronie, weil Sie Ihre Funktionen immer noch im synchronen Paradigma schreiben.

In der Asynchronie sollten Sie Callbacks an Ereignisse anhängen. Sie sollten kein Ergebnis von einer asynchronen Funktion wie get_latest_results() erwarten, sondern ihr eine Callback-Funktion als Argument übergeben, die aufgerufen wird, wenn die Ergebnisse bereit sind. Der Callback wird dann alles Notwendige mit Ihren Ergebnissen tun:

var get_latest_results = function (feedId, readyCallback) {
    client.get('feed:' + feedId + ':latest', function (err, res) {
        var latest_reading_key = res.toString();
        client.hgetall(latest_reading_key, function (err, res) {
            readyCallback(res);                           //--- Trigger Callback
        });
    });
    // Wie kann ich einen Rückgabewert für diese Funktion angeben? //--- Das tun Sie nicht
}

Dann können Sie Ihre Funktion folgendermaßen aufrufen:

get_latest_results(1000, function (result) {
   //--- Alles tun, was mit dem neuesten Ergebnis getan werden muss...
});

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X