Reputation: 3861
I'm using Firestore, Cloud Functions and Dialogflow to create a Google Home app. My cloud function should return a calculation based on values in a collection, but I can only return a Promise.
// query firestore based on user
var transactions = db.collection('accounts')
.doc(request.body.result.parameters.accountowner)
.collection('transactions');
var accountbalance = await transactions.get()
.then(snapshot => {
var workingbalance = 0
snapshot.forEach(doc => {
workingbalance = workingbalance + doc.data().amount;
});
return workingbalance
})
.catch(err => {
console.log('Error getting transactions', err);
});
console.log(accountbalance)
balanceresponse = {
"speech": request.body.result.parameters.accountowner + " has a balance of $" + accountbalance,
"displayText": request.body.result.parameters.accountowner + " has an account balance of $" + accountbalance,
"data": {},
"contextOut": [],
"source": "system"
}
response.send(balanceresponse);
How can I wait for the promise to return the actual value before calling response.send? I have also tried to put the response.send inside a then, but the function completes and sends headers before the operation completes.
Upvotes: 3
Views: 5828
Reputation: 50731
If you're working with promises, you need to return values as part of the Promise.then chain. This is usually done by chaining a bunch of .then()
calls/blocks together. Remember, the then()
portion will only be called when a Promise resolves.
In your case, it looks like you can just generate balanceresponse
and call the response.send()
after you calculate workingbalance
, inside the same block of code. The call to response.send()
doesn't need to be at the end of the function. So you might have that block look something like:
.then(snapshot => {
var workingbalance = 0
snapshot.forEach(doc => {
workingbalance = workingbalance + doc.data().amount;
});
balanceresponse = {
"speech": request.body.result.parameters.accountowner + " has a balance of $" + workingbalance,
"displayText": request.body.result.parameters.accountowner + " has an account balance of $" + workingbalance,
"data": {},
"contextOut": [],
"source": "system"
}
response.send(balanceresponse);
})
If, for some reason, you wanted to separate the calculation and compute the balanceresponse
in a different block, you could do so. I don't necessarily recommend this, but it has some merits (for example, you could put multiple catch blocks after each part, which I've shown here):
// query firestore based on user
var transactions = db.collection('accounts')
.doc(request.body.result.parameters.accountowner)
.collection('transactions');
await transactions.get()
.then(snapshot => {
var workingbalance = 0
snapshot.forEach(doc => {
workingbalance = workingbalance + doc.data().amount;
});
return workingbalance
})
.catch(err => {
console.log('Error getting transactions', err);
});
.then( accountbalance => {
balanceresponse = {
"speech": request.body.result.parameters.accountowner + " has a balance of $" + accountbalance,
"displayText": request.body.result.parameters.accountowner + " has an account balance of $" + accountbalance,
"data": {},
"contextOut": [],
"source": "system"
}
response.send(balanceresponse);
})
.catch(err => {
console.log('Error sending response', err);
});
Upvotes: 1