Reputation: 357
I wrote this firebase function that triggers when data is added, it summarizes the child values and updates the total value field.
export const updateTotalAnswersCounts = functions.database
.ref('/CurrentGame/answers/{aid}').onWrite((change, context) => {
var collectionRef = change.after.ref.parent;
let total = 0;
collectionRef.once('value',(snapshot)=>{
console.log('snapshot',snapshot.val())
snapshot.forEach((childSnapshot)=>{
if(childSnapshot.val()!=null){
console.log('childSnapshot',childSnapshot.val())
total+=Number(childSnapshot.val())
}
return false;
})
const updates = {}
updates['/totalAnswersCount'] = total;
firebase.ref('/CurrentGame').update(updates)
})
return true;
});
the function trigger works when I add new value to 'answers' node then it takes all the numbers (in this photo 1+2+11) then it update the totalAnswersCount to the sum = 14.
this add operation
addAnswer() {
let answer = 3;
let userInfo = {
uid: this.uid,
gid: '1',
qid: '2',
aid: '3'
}
const answer_ref = firebase.database().ref(`CurrentGame/answers/${answer}`);
const users_answers_ref = firebase.database().ref(`GameQuestionStats/${this.user.uid}/${userInfo.qid}`);
// Return the promise from countRef.transaction() so our function
// waits for this async event to complete before it exits.
return answer_ref.transaction((current) => {
return (current || 0) + 1;
}).then(() => {
return users_answers_ref.set(userInfo,{merge:true})
});
}
this firebase function works alternately
Upvotes: 0
Views: 85
Reputation: 83093
The reason is that you have to chain the Promises (and therefore return a promise at each chaining step).
The following should work:
export const updateTotalAnswersCounts = functions.database
.ref('/CurrentGame/answers/{aid}').onWrite((change, context) => {
const collectionRef = change.after.ref.parent;
let total = 0;
return collectionRef.once('value', (snapshot) => {
console.log('snapshot', snapshot.val())
snapshot.forEach((childSnapshot) => {
if (childSnapshot.val() != null) {
console.log('childSnapshot', childSnapshot.val())
total += Number(childSnapshot.val())
}
})
}).then(() => {
const updates = {}
updates['/totalAnswersCount'] = total
return firebase.ref('/CurrentGame').update(updates)
}).catch(error => {
console.log(error);
//Error treatment
});
});
I would suggest that you look at Doug Stevenson's videos on the subject:
https://www.youtube.com/watch?v=7IkUgCLr5oA&t=515s
https://www.youtube.com/watch?v=652XeeKNHSk
https://www.youtube.com/watch?v=d9GrysWH1Lc&t=4s
Note that case nbr 2 (it has delay and updates after 3-4 sec.) is a classic behavior when you don't return a promise in a Cloud Function.
Upvotes: 1
Reputation: 431
One change I would recommend is to make use of the value from change and append the sum to your total answers count.
eg: total = total+(newvalue-oldvalue);
this will save you the trouble from loading all the values from 'once' operation, which will be very costly if your data grows.
Finally, the reason (which I suspect) for your alternative working might be because of promises, which are getting executed from your 'once' operation. Hope this helps you.
Upvotes: 0