admin管理员组文章数量:1430567
I'm building an Alexa Skill, which requires me to listen to a Firebase Realtime Database. In one particular part of the skill, I need to write a JSON object to Firebase, consisting of two fields, "intent", with an insignificant value, and "done", with a value of false
.
Then, I wait for another device listening to this database to register this change, at which point it creates another field, named "result", with some numerical value, and changes the value of "done" to true.
Then the original function (test1
) should recognize when the value of "done" is true, and then retrieve the value of "result".
What I'm having trouble with is ing up with a function that does all of these read/write operations before my main (asynchronous) function finishes. As the title suggests, AWS Lambda times out for some reason, and I am unable to read the value of "result".
This is the function I'm using:
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),
{}
)
);
});
}
This is the output of the console (in 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
The following is the structure of the Firebase data:
"done" is initially false. When the other device add "result", it also updates the value of "done" to true. "148434459..." is targetRef.
Your help is truly appreciated. I will supply more info if needed.
I'm building an Alexa Skill, which requires me to listen to a Firebase Realtime Database. In one particular part of the skill, I need to write a JSON object to Firebase, consisting of two fields, "intent", with an insignificant value, and "done", with a value of false
.
Then, I wait for another device listening to this database to register this change, at which point it creates another field, named "result", with some numerical value, and changes the value of "done" to true.
Then the original function (test1
) should recognize when the value of "done" is true, and then retrieve the value of "result".
What I'm having trouble with is ing up with a function that does all of these read/write operations before my main (asynchronous) function finishes. As the title suggests, AWS Lambda times out for some reason, and I am unable to read the value of "result".
This is the function I'm using:
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),
{}
)
);
});
}
This is the output of the console (in 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
The following is the structure of the Firebase data:
"done" is initially false. When the other device add "result", it also updates the value of "done" to true. "148434459..." is targetRef.
Your help is truly appreciated. I will supply more info if needed.
Share Improve this question edited Jan 13, 2017 at 22:39 Miki P asked Jan 13, 2017 at 20:45 Miki PMiki P 6521 gold badge9 silver badges22 bronze badges 1- Hope my answer here helps stackoverflow./a/45266181/2073325 – gchao Commented Jul 23, 2017 at 14:29
5 Answers
Reset to default 3The problem is that on
does not return a promise. Instead, it returns the callback function that was passed as a parameter. on
will invoke the callback for the initial data and then again for any changes made to the data.
You most likely want to use once
, which does return a promise:
...
}).then(function () {
return targetRef.orderByChild("done").equalTo(true).once("value");
}).then(function (snapshot) {
snapshot.forEach(function (childSnapshot) {
console.log(childSnapshot.val());
});
})
...
Note that the promise's resolved snapshot will contain zero or more children that matched the query. To enumerate the children, you can use the snapshot's forEach
method.
I found out the hard way that initializing firebase in a lambda function (e.g. via firebase-admin) will prevent the function from terminating (until the default 6-second timeout) unless you call app.delete()
on the firebase app instance. Additionally, you should make sure that every time your run your lambda function you are using a new firebase app instance otherwise you will run into problems.
const app = admin.initializeApp({});
app.database().ref('child').set('hello').then(() => {
return app.delete();
}).then(() => {
let response = {}; // whatever
callback(null, response);
});
Your Lambda function probably times out after 4 seconds because you set this value when configuring the Lambda function. In order for the your function to wait for the external thing to happen, you can schedule a function to query the value regularly with setTimeout() until the value is there. If that takes longer than 4 seconds, you need to increase the functions timeout, too.
From the AWS Lambda documentation:
Q: How long can an AWS Lambda function execute?
All calls made to AWS Lambda must plete execution within 300 seconds. The default timeout is 3 seconds, but you can set the timeout to any value between 1 and 300 seconds.
I would suggest that you are going to have problems trying to wait for Firebase events from inside a Lambda function. Lambda is designed to be called with data and process data and exit, not to wait for other events to happen. You would be better off using some kind of VPS and running a general Node process to do the database work. Lambda pushing data into Firebase is fine, but what you are trying to achieve with Firebase might be the wrong approach.
You are calling the function before the other function is being called. Try npm sleep() or setTimeout() to give your function a pause.
本文标签: javascriptListening to Firebase database in AWS Lambda times outStack Overflow
版权声明:本文标题:javascript - Listening to Firebase database in AWS Lambda times out - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745547462a2662772.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论