Manspof
Manspof

Reputation: 357

Firebase trigger functions works alternately

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})
    });
}

enter image description here

this firebase function works alternately

  1. when I first load the app, it node update and not make any update.
  2. sometimes it has delay and updates after 3-4 sec.
  3. sometimes it updates in real time and works fine.

Upvotes: 0

Views: 85

Answers (2)

Renaud Tarnec
Renaud Tarnec

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

Praveen Kumar A X
Praveen Kumar A X

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

Related Questions