17

私は Java のバックグラウンドを持っているので、Lambda に必要な Javascript 規則について少し初心者です。

前のタスクの結果に応じて、特定の順序でいくつかの AWS タスクを実行するためのラムダ関数があります。

各タスクがその結果を非同期に報告することを考えると、正しい方法ですべてが正しい順序で発生し、1 つの操作の結果が次の関数の呼び出しに使用できるようになるかどうか疑問に思っています。

前の関数のコールバックで各関数を呼び出す必要があるようですが、それはある種の深い入れ子になり、それがこれを行う適切な方法であるかどうか疑問に思うようです。

たとえば、これらの関数には、DynamoDB getItem が必要で、その後にエンドポイントを取得するための SNS への呼び出し、メッセージを送信するための SNS 呼び出し、DynamoDB への書き込みが続きます。

そのすべての非同期性を考慮して、ラムダJavaScriptでそれを行う正しい方法は何ですか?

4

8 に答える 8

4

@jonathanbaraldi からの回答は気に入っていますが、Promises で制御フローを管理した方がよいと思います。Q ライブラリにはnbind、aws-sdk などのノード スタイルのコールバック API を promise に変換するのに役立つ便利な関数がいくつかあります。

この例では、電子メールを送信し、電子メールの応答が返ってきたらすぐに 2 番目の電子メールを送信します。これは基本的に、複数のサービスを順番に呼び出して求められたものです。私はthen約束の方法を使用して、それを垂直方向に読みやすい方法で管理しています。catchエラーの処理にも使用します。単純にコールバック関数をネストするだけで、はるかに読みやすくなると思います。

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@company.com.br'];
    var from = 'site@company.com.br';

    // 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();
    }
}
于 2015-03-20T08:22:48.910 に答える
2

Lambda についてはわかりませんが、非同期関数をシーケンスする方法としてノード非同期ライブラリを調べる必要があります。

async により、質問で言及した深いネストの問題がなくても、私の人生はずっと楽になり、私のコードははるかに整然としたものになりました。

典型的な非同期コードは次のようになります。

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(); }
});

上記のリンクで非同期ドコを見てください。シリアル、パラレル、ウォーターフォールなど、多くの便利な関数があります。Async は積極的に維持されており、非常に信頼できるようです。

幸運を!

于 2014-12-31T06:31:11.590 に答える
1

頭に浮かぶ非常に具体的な解決策は、Lambda 呼び出しのカスケードです。たとえば、次のように記述できます。

  1. Lambda 関数は DynamoDB から何かを取得し、呼び出します…</li>
  2. …SNS を呼び出してエンドポイントを取得し、次に…を呼び出す Lambda 関数</li>
  3. …SNS を介してメッセージを送信し、次に…を呼び出す Lambda 関数</li>
  4. …DynamoDB に書き込む Lambda 関数

これらの関数はすべて、前の関数からの出力を入力として受け取ります。もちろん、これは非常にきめ細かく、特定の呼び出しをグループ化することもできます。このようにすることで、少なくとも JS コードのコールバック地獄を回避できます。

(ちなみに、DynamoDB が Lambda とどの程度うまく統合されているかはわかりません。AWS は、Lambda を介して処理できるレコードの変更イベントを発行する場合があります。)

于 2015-10-06T07:42:52.360 に答える
-2

デフォルトでは、JavaScript は非同期です。

したがって、あなたがしなければならないことはすべて、それらのライブラリを使用することではなく、使用できますが、これを解決する簡単な方法があります。このコードでは、イベントからのデータを含むメールを送信しましたが、必要に応じて、関数内にさらに関数を追加する必要があります。

重要なのは、 context.done(); の場所です。彼はあなたの Lambda 関数を終了させようとしています。彼を最後の関数の最後に配置する必要があります。

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@company.com.br'];
    var from = 'site@company.com.br';

    // 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();
          }
     });
}
于 2015-02-18T04:00:08.660 に答える