2014-12-31 3 views
16

Ich komme aus einem Java-Hintergrund, also ein bisschen ein Neuling auf Javascript Konventionen für Lambda benötigt.Wie strukturieren Sie sequenzielle AWS-Serviceaufrufe innerhalb von Lambda, wenn alle Aufrufe asynchron sind?

Ich habe eine Lambda-Funktion, die mehrere AWS-Aufgaben in einer bestimmten Reihenfolge ausführen soll, abhängig vom Ergebnis der vorherigen Aufgabe.

Vorausgesetzt, dass jede Aufgabe ihre Ergebnisse asynchron meldet, frage ich mich, ob der richtige Weg sicherstellt, dass alle in der richtigen Reihenfolge passieren und die Ergebnisse einer Operation für den Aufruf der nächsten Funktion verfügbar sind.

Es scheint, wie ich jede Funktion in den Rückruf des Standes der Funktion invoike haben, aber wie das scheint wird eine Art tiefen Verschachtelung und sich fragen, ob das der richtige Weg ist, dies zu tun.

Zum Beispiel erfordert eine dieser Funktionen ein dynamoDB getItem, gefolgt von einem Aufruf an SNS, um einen Endpunkt zu erhalten, gefolgt von einem SNS-Aufruf zum Senden einer Nachricht, gefolgt von einem DynamoDB-Schreiben.

Was ist der richtige Weg, dies in Lambda Javascript zu tun, Buchhaltung für all diese Asynchronität?

+0

Haben Sie eine Lösung gefunden? – Casper

Antwort

2

Ich weiß nicht, Lambda, aber Sie sollten in den Knoten async library als eine Möglichkeit, asynchrone Funktionen Sequenz.

async hat mein Leben viel einfacher gemacht und mein Code viel ordentlicher ohne das tiefe Verschachtelungsproblem, das Sie in Ihrer Frage erwähnt haben.

Typische Code async könnte wie folgt aussehen:

async.waterfall([ 
    function doTheFirstThing(callback) { 
     db.somecollection.find({}).toArray(callback); 
    }, 
    function useresult(dbFindResult, callback) { 
     do some other stuff (could be synch or async) 
     etc etc etc 
     callback(null); 
], 
function (err) { 
    //this last function runs anytime any callback has an error, or if no error 
    // then when the last function in the array above invokes callback. 
    if (err) { sendForTheCodeDoctor(); } 
}); 

einen Blick auf die async doco haben oben auf den Link. Es gibt viele nützliche Funktionen für seriell, parallel, Wasserfall und viele mehr. Async wird aktiv gepflegt und scheint sehr zuverlässig zu sein.

viel Glück!

-2

standardmäßig Javascript ist asynchron.

Also alles, was Sie tun müssen, ist es nicht, diese Bibliotheken zu verwenden, Sie können, aber es gibt einfache Möglichkeiten, dies zu lösen. In diesem Code habe ich die E-Mail mit den Daten gesendet, die aus dem Ereignis stammen, aber wenn Sie möchten, müssen Sie lediglich weitere Funktionen in Funktionen hinzufügen.

Was wichtig ist, ist der Ort, an dem Ihr context.done(); wird sein, er wird deine Lambda-Funktion beenden. Sie müssen ihn in das Ende der letzten Funktion setzen.

var AWS = require('aws-sdk');  
AWS.config.credentials = { "accessKeyId": "AAAA","secretAccessKey": "BBBB"}; 
AWS.config.region = 'us-east-1'; 
var ses = new AWS.SES({apiVersion: '2010-12-01'}); 

exports.handler = function(event, context) { 

    console.log(event.nome); 
    console.log(event.email); 
    console.log(event.mensagem); 

    nome = event.nome; 
    email = event.email; 
    mensagem = event.mensagem; 

    var to = ['[email protected]']; 
    var from = '[email protected]'; 

    // Send email 
    mensagem = ""+nome+"||"+email+"||"+mensagem+""; 

    console.log(mensagem); 
    ses.sendEmail({ 
     Source: from, 
     Destination: { ToAddresses: to }, 
     Message: { 
      Subject: { 
       Data: 'Form contact our Site' 
      }, 
      Body: { 
       Text: { 
        Data: mensagem, 
       } 
      } 
     } 
    }, 
    function(err, data) { 
     if (err) { 
      console.log("ERROR="+err, err.stack); 
      context.done(); 
      } else { 
      console.log("EMAIL SENT="+data); 
      context.done(); 
      } 
    }); 
} 
4

Ich mag die Antwort von @jonathanbaraldi aber ich denke, es wäre besser, wenn Sie Steuerungsablauf mit Versprechungen verwalten. Die Q-Bibliothek verfügt über einige Komfortfunktionen wie nbind, mit deren Hilfe die Callback-APIs im Knotendesign wie die aws-sdk in Versprechungen umgewandelt werden können.

Also in diesem Beispiel werde ich eine E-Mail senden, und dann, sobald die E-Mail-Antwort zurückkommt, werde ich eine zweite E-Mail senden. Dies ist im Wesentlichen, was gefragt wurde, mehrere Dienste nacheinander aufzurufen.Ich verwende die then Methode von Versprechen, das vertikal lesbar zu verwalten. Verwenden Sie auch catch, um Fehler zu behandeln. Ich denke, es liest sich viel besser, einfach nur Callback-Funktionen verschachteln.

var Q = require('q'); 
var AWS = require('aws-sdk');  
AWS.config.credentials = { "accessKeyId": "AAAA","secretAccessKey": "BBBB"}; 
AWS.config.region = 'us-east-1'; 

// Use a promised version of sendEmail 
var ses = new AWS.SES({apiVersion: '2010-12-01'}); 
var sendEmail = Q.nbind(ses.sendEmail, ses); 

exports.handler = function(event, context) { 

    console.log(event.nome); 
    console.log(event.email); 
    console.log(event.mensagem); 

    var nome = event.nome; 
    var email = event.email; 
    var mensagem = event.mensagem; 

    var to = ['[email protected]']; 
    var from = '[email protected]'; 

    // Send email 
    mensagem = ""+nome+"||"+email+"||"+mensagem+""; 

    console.log(mensagem); 

    var params = { 
     Source: from, 
     Destination: { ToAddresses: to }, 
     Message: { 
     Subject: { 
      Data: 'Form contact our Site' 
     }, 
     Body: { 
      Text: { 
       Data: mensagem, 
      } 
     } 
    }; 

    // Here is the white-meat of the program right here. 
    sendEmail(params) 
     .then(sendAnotherEmail) 
     .then(success) 
     .catch(logErrors); 

    function sendAnotherEmail(data) { 
     console.log("FIRST EMAIL SENT="+data); 

     // send a second one. 
     return sendEmail(params); 
    } 

    function logErrors(err) { 
     console.log("ERROR="+err, err.stack); 
     context.done(); 
    } 

    function success(data) { 
     console.log("SECOND EMAIL SENT="+data); 
     context.done(); 
    } 
} 
0

Ich möchte die folgende Lösung anbieten, die einfach eine verschachtelte Funktionsstruktur erstellt.

// start with the last action 
var next = function() { context.succeed(); }; 

// for every new function, pass it the old one 
next = (function(param1, param2, next) { 
    return function() { serviceCall(param1, param2, next); }; 
})("x", "y", next); 

Was das bedeutet ist, alle Variablen für die Funktion aufrufen, die Sie machen wollen kopieren, dann nistet sie in den vorherigen Anruf. Sie sollten Ihre Ereignisse rückwärts planen. Das ist genau das gleiche wie eine Callback-Pyramide, funktioniert aber, wenn Sie nicht vorher die Struktur oder die Anzahl der Funktionsaufrufe kennen. Sie müssen die Funktion in eine Closure einfügen, damit der korrekte Wert kopiert wird.

Auf diese Weise bin ich in der Lage, AWS-Serviceaufrufe so zu sequenzieren, dass sie 1-2-3 gehen und mit dem Schließen des Kontextes enden. Vermutlich könnte man ihn statt dieser Pseudorecursion auch als Stack strukturieren.

1

Eine sehr spezifische Lösung, die in den Sinn kommt, ist die Kaskadierung von Lambda-Aufrufen. Zum Beispiel könnten Sie schreiben:

  1. Ein Lambda-Funktion etwas von DynamoDB bekommt, ruft dann ...
  2. ... eine Lambda-Funktion, die SNS ruft einen Endpunkt zu erhalten, dann ruft ...
  3. ... eine Lambda-Funktion, sendet eine Nachricht über SNS, dann ruft ...
  4. ... eine Lambda-Funktion, die

Alle diese Funktionen übernehmen die Ausgabe von der vorherigen Funktion als Eingabe für DynamoDB schreibt. Dies ist natürlich sehr feingranular, und Sie könnten sich entscheiden, bestimmte Anrufe zu gruppieren. Auf diese Weise vermeiden Sie zumindest die Callback-Hölle in Ihrem JS-Code.

(Als Randbemerkung, ich bin nicht sicher, wie gut DynamoDB mit Lambda integriert. AWS Änderungsereignisse für Aufzeichnungen emittieren könnte, die dann durch Lambda verarbeitet werden kann.)

0

sah einfach diesen alten Thread. Beachten Sie, dass zukünftige Versionen von JS dies verbessern werden. Werfen Sie einen Blick auf die ES2017 async/await-Syntax, die ein asynchron verschachteltes Callback-Problem in einen sauberen sync-ähnlichen Code strafft. Jetzt gibt es einige polyfills, die Ihnen diese Funktionalität basierend auf ES2016-Syntax bieten können.

Als letzte FYI - AWS Lambda now supports .Net Core, die diese saubere asynchrone Syntax aus der Box bietet.

Verwandte Themen