在 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 错误网关结束,之后将无法接收到调用。所有路径都必须设置上下文。
我发现了很多关于这个主题的评论,但 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 错误网关结束,之后将无法接收到调用。所有路径都必须设置上下文。