我正在建立一个Alexa技能,这需要我收听Firebase实时数据库。在技能的一个特定部分,我需要向Firebase写一个JSON对象,包括两个字段," intent",值不重要,"完成",带有值false
。
然后,我等待另一个监听此数据库的设备注册此更改,此时它会创建另一个字段,名为" result",带有一些数值,并更改&#34的值;完成"为真。
然后原始函数(test1
)应该识别"完成"的值。是的,然后检索"结果"。
我遇到的麻烦是在我的主(异步)函数完成之前提供一个执行所有这些读/写操作的函数。正如标题所示,AWS Lambda由于某种原因超时,我无法读取"结果"的值。
这是我使用的功能:
function test1(intentName, targetRef, context) {
console.log("writing");
targetRef.set({
intent: intentName,
done: false
}).then(function() {
return targetRef.orderByChild("done").equalTo(true).on("value");
}).then(function(snapshot) {
var res = snapshot.val().result;
console.log("Res: " + res);
context.succeed( //context.succeed should be called after "result" has a value.
generateResponse(
buildSpeechletReponse("The result is" + processNumbersForSpeech(res), true),
{}
)
);
});
}
这是控制台的输出(在AWS Lambda中):
20:05:31
START RequestId: a25d2354-d9cb-11e6-b80a-f35142a5f45f Version: $LATEST
20:05:31
2017-01-13T20:05:31.464Z a25d2354-d9cb-11e6-b80a-f35142a5f45f writing
20:05:35
END RequestId: a25d2354-d9cb-11e6-b80a-f35142a5f45f
20:05:35
REPORT RequestId: a25d2354-d9cb-11e6-b80a-f35142a5f45f Duration: 4001.15 ms Billed Duration: 4000 ms Memory Size: 128 MB Max Memory Used: 39 MB
20:05:35
2017-01-13T20:05:35.335Z a25d2354-d9cb-11e6-b80a-f35142a5f45f Task timed out after 4.00 seconds
以下是Firebase数据的结构:
"完成"最初是假的。当其他设备添加"结果"时,它还会更新"完成"为真。 " 148434459 ..."是targetRef。
真的很感激你的帮助。如果需要,我会提供更多信息。
答案 0 :(得分:3)
问题是on
没有返回承诺。相反,它返回作为参数传递的回调函数。 on
将调用初始数据的回调,然后再次调用对数据所做的任何更改。
你很可能想要使用once
,它会返回一个承诺:
...
}).then(function () {
return targetRef.orderByChild("done").equalTo(true).once("value");
}).then(function (snapshot) {
snapshot.forEach(function (childSnapshot) {
console.log(childSnapshot.val());
});
})
...
请注意,promise的已解析快照将包含零个或多个与查询匹配的子项。要枚举孩子,您可以使用快照的forEach
方法。
答案 1 :(得分:2)
我发现在lambda函数中初始化firebase(例如通过firebase-admin)很难阻止函数终止(直到默认的6秒超时),除非你在firebase app上调用app.delete()
实例。此外,您应该确保每次运行lambda函数时都使用新的firebase应用程序实例,否则会遇到问题。
const app = admin.initializeApp({});
app.database().ref('child').set('hello').then(() => {
return app.delete();
}).then(() => {
let response = {}; // whatever
callback(null, response);
});
答案 2 :(得分:0)
您的Lambda函数可能会在4秒后超时,因为您在配置Lambda函数时设置了此值。为了使您的函数等待外部事件发生,您可以安排一个函数来定期使用setTimeout()查询该值,直到该值存在。如果时间超过4秒,则还需要增加函数超时。
答案 3 :(得分:0)
来自AWS Lambda文档:
问: AWS Lambda函数可以执行多长时间?
对AWS Lambda的所有调用必须在300秒内完成执行。默认超时为3秒,但您可以将超时设置为1到300秒之间的任何值。
我建议您在尝试从Lambda函数内等待Firebase事件时遇到问题。 Lambda旨在通过数据和流程数据调用并退出,而不是等待其他事件发生。您最好使用某种VPS并运行一般的Node进程来完成数据库工作。 Lambda将数据推送到Firebase很好,但是您尝试使用Firebase实现的可能是错误的方法。
答案 4 :(得分:-1)
在调用其他函数之前调用该函数。尝试使用npm sleep()或setTimeout()为您的函数暂停。