在 lambda 处理程序中使用请求承诺将放弃调用

using request promise in lambda handler will abandon call

我发现了很多关于这个主题的评论,但 none 对我来说确实有用。我正在构建一个 facebook 机器人。现在说我只想将文本回显给调用者。我有一个使用 ec2 的工作示例。当移动到 lambda 时,它不起作用。这是我的代码:

exports.handler = (event, context, callback) => {
...
} else if (event.httpMethod == 'POST') {
    var data = JSON.parse(event.body);
    if (data.object == 'page') {
        data.entry.forEach(function(pageEntry) {
            // Iterate over each messaging event
            pageEntry.messaging.forEach(function(messagingEvent) {
                if (messagingEvent.message) {
                    receivedMessage(messagingEvent);
                }
            });
        });
    }
    //if I only use callback like the documentation states, gateway always says 502, regardless of the message content in second param, or even using no params
    //callback(null, JSON.stringify({"statusCode": 200, "headers": {"content-type":"application.json"}, "body": ""}));
    //if i answer using succeed, gateway says 200 ok, bot never gets post
    context.succeed({"statusCode": 200, "headers": {"content-type":"application.json"}, "body": ""});
}

function receivedMessage(event) {
var senderID = event.sender.id;
var messageText = message.text;
if (messageText) {
    var messageData = {
        recipient: {
          id: senderID
        },
        message: {
          text: messageText,
          metadata: "DEVELOPER_DEFINED_METADATA"
        }
      };
    callSendAPI(messageData);
}

}

function callSendAPI(messageData) {
request({
    uri: 'https://graph.facebook.com/v2.8/me/messages',
    qs: { access_token: PAGE_ACCESS_TOKEN },
    method: 'POST',
    json: messageData
}).then(function(body) {
    console.log('success');
}).catch(function(err) {
    console.error("Failed calling Send API", err);
});

}

我尝试移动 .then 部分中的 context.succeed,但网关获得 502。如果我在 aws lambda 控制台中点击 'test' 按钮,Messenger 会收到消息。 promise 似乎随调用而存在,但未触发。

我阅读了很多关于这个主题的帖子并尝试了很多答案,但都没有成功。我读到其他人在使用 claudiajs 时遇到了同样的问题,有或没有 claudia 承诺。

现在我正在考虑回到 ec2。任何帮助表示赞赏。

使用 callback(...)context.succeed(...) 的区别在于,context.succeed(...) 调用会使 Lambda 等待空事件循环。有关详细信息,请参阅此 link:http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html

在您的代码示例中,当您调用 callback(...) 时,事件循环中仍然有来自 receivedMessage 和 callSendAPI 的事件。该代码不会链接结果承诺和 'wait',以便在调用 callback(...) 之前完成那些承诺。您还可以在两种方法中的每一种中建立响应并调用回调。

我建议从 receivedMessage 和 callSendAPI 返回承诺,并在处理完所有消息后调用回调。

类似这样的方法可能有效:

/* This goes inside your handler */
//using Bluebird promises
Promise.all(Promise.map(data.entry, pageEntry => {
    // Iterate over each messaging event
    return Promise.all(
             pageEntry.messaging
                  .filter(e => e.message)
                  .map(messagingEvent => 
                     receivedMessage(messagingEvent)));
 })).then(res => callback(null, res))
   .catch(err => callback(err));
/* The code above goes in your handler */

function receivedMessage(event) {
    var senderID = event.sender.id;
    var messageText = message.text;
    if (messageText) {
       var messageData = {
                recipient: {
                  id: senderID
                },
                message: {
                    text: messageText,
                    metadata: "DEVELOPER_DEFINED_METADATA"
                }
              };
       return callSendAPI(messageData);
    } else {
       return Promise.resolve({});
    }
}

function callSendAPI(messageData) {
         return request({
               uri: 'https://graph.facebook.com/v2.8/me/messages',
               qs: { access_token: PAGE_ACCESS_TOKEN },
               method: 'POST',
               json: messageData
          });
}

本文档声明在 API 网关 lambda 代理的情况下必须设置上下文:https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html#api-gateway-simple-proxy-for-lambda-output-format

我遇到的问题是,在捕获错误时,我没有调用 context.fail,它以 502 错误网关结束,之后将无法接收到调用。所有路径都必须设置上下文。