Reputation: 2097
Can anyone help me determine why firebase isn't returning the value from a cloud function? It seems like reading from on database change is simple, but when doing a http on request, firebase functions just hangs and finally times out.
exports.getTotalPrice = functions.https.onRequest((req, res) => {
var data = "";
req.on('data', function(chunk){ data += chunk})
req.on('end', function(){
req.rawBody = data;
req.jsonBody = JSON.parse(data);
res.end(next(req.jsonBody));
})
});
function next(json) {
var total = 0;
for(var i = 0; i < json.products.length; i++) {
//Get product by UPC
console.log(order.products[i].upc);
codeRef.orderByKey()
.equalTo(order.products[i].upc)
.once('value', function(snap) {
console.log(snap.val()); // returns `null`
return (snap.val()[0].msrp);
})
//Multiply the price of the product by the quantity
console.log(order.products[i].quantity);
//add it to the total price
}
}
Upvotes: 1
Views: 1062
Reputation: 40582
You are running several asynchronous functions but you aren't informing your function when they are done. The function needs to return a promise to succeed here.
Note also that if the database call fails, it's going to do so silently here. So you should capture errors and report those as well.
Note also that you're storing your distributed JSON data as arrays, which you probably shouldn't.
Note also that you're using .orderByKey().equalTo()
when you could just be using .child(upc)
.
So what you've essentially got here is a mess. You need to spend some time in the guide and samples--you're going to spend a lot of time thrashing like this if you don't.
For a starting point, reduce your code set to the simplest use case runs as expected:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.testDbOp = functions.https.onRequest((req, res) => {
return admin.database()
.ref('/foo')
.once('value')
.then(snap => res.send(JSON.stringify(snap.val()))
.catch(e => console.error(e));
});
Once you have that working, if you want to fetch several values asynchronously, you can do that with Promise.all(), something like this:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.testDbOp = functions.https.onRequest((req, res) => {
const promises = [];
const output = {};
const jsonData = {....};
jsonData.products.forEach(product => {
promises.push( codeRef.child(product.upc).once('value')
.then(snap => output[product.upc] = snap.val()[0].msrp);
});
return Promise.all(promises).then(() => res.send(JSON.stringify(output));
});
Upvotes: 2
Reputation: 7324
It doesn't seem like you are calling the database at all. I only see functions.https.onRequest()
which is a http trigger https://firebase.google.com/docs/functions/http-events.
If you wanted to call the database it would have to be something more like functions.database.ref('/').onWrite(event => {})
so that it references the database https://firebase.google.com/docs/functions/database-events.
onWrite refers to any kind of change at that point in the database, not just writing to the database. https://firebase.google.com/docs/functions/database-events#reading_the_previous_value
Upvotes: 1