Firebase realtime database triggers: When async and when not

独自空忆成欢 提交于 2019-12-12 09:22:33

问题


In the documentation on Firebase triggers, we do not see the async word: https://firebase.google.com/docs/functions/database-events#reading_the_previous_value Let's say I have two versions of a function, one is with async, and one without, like so:

exports.recountTotalCaloriesOnUpdate2 = functions.database.ref('/mealsOf/{userId}/{day}/meals')
    .onUpdate(
        (change,context) => {
            let uid= context.params.userId;
            let day= context.params.day;
            if ( !change.after.exists() ) return null ;
            if ( !change.before.exists() ) return null ;
            const collectionRef = change.after.ref;
            let finalSum = collectionRef.ref.once('value').then((snap) => {
                let sum = 0;
                snap.forEach((child) => {
                    //console.log(child.val().numCalories);
                    sum = sum + parseInt(child.val().numCalories);
                });
                return sum;
            });
            /*
            return await counterRef.ref.transaction((cnt) => {
                 return finalSum;
            });
            */
            return dbroot.ref(`mealsOf/${uid}/${day}/totalCalories`).set(finalSum);
            /*
            return await dbroot.ref(`mealsOf/${uid}/${day}/totalCalories`).set(finalSum).then( (a) => {
                return null ;
            }).catch( (error) => {
                return null ;
            });
            */
        }
    );

and with async:

exports.recountTotalCaloriesOnUpdate2 = functions.database.ref('/mealsOf/{userId}/{day}/meals')
    .onUpdate(
        async(change,context) => {
            let uid= context.params.userId;
            let day= context.params.day;
            if ( !change.after.exists() ) return null ;
            if ( !change.before.exists() ) return null ;
            const collectionRef = change.after.ref;
            let finalSum = await collectionRef.ref.once('value').then((snap) => {
                let sum = 0;
                snap.forEach((child) => {
                    //console.log(child.val().numCalories);
                    sum = sum + parseInt(child.val().numCalories);
                });
                return sum;
            });
            /*
            return await counterRef.ref.transaction((cnt) => {
                 return finalSum;
            });
            */
            //return dbroot.ref(`mealsOf/${uid}/${day}/totalCalories`).set(finalSum);
            return await dbroot.ref(`mealsOf/${uid}/${day}/totalCalories`).set(finalSum).then( (a) => {
                return null ;
            }).catch( (error) => {
                return null ;
            });
        }
    );

What is the difference? Does it make a difference to Firebase? Also, in calculating finalSum, my let finalSum = await ... am I making sure this finalSum is available in the subsequent lines, i.e. does the thread of execution .join() the calculation, in Java's parlance? But the real problem with this code is that

return await dbroot.ref(`mealsOf/${uid}/${day}/totalCalories`).set(finalSum).then( (a) => {
                return null ;
            }).catch( (error) => {
                return null ;
            });

always gives me message: for the case without async, and for the case with async.

What I have is a path mealsOf/{userId}/{day}/meals/{mealId}, and I push a new meal there. So I put this trigger to update the counter at mealsOf/{userId}/{day}/totalCalories whenever a write/update happens at the path mealsOf/{userId}/{day}/meals. How to deal with the above exceptions?

EDIT: You can read about async/await elsewhere, e.g. https://hackernoon.com/understanding-async-await-in-javascript-1d81bb079b2c (just a random link, lost of material out there!) As to my particular case, I let the async be there, heeded to the actual error message, and replace the last line with this:

return dbroot.ref(`mealsOf/${uid}/${day}/totalCalories`).set(""+finalSum, (error) => {
                if ( error )
                    console.log(error.message);
            });

and finally got my tests pass with clean execution. So, NaN tells us it is safest to convert everything into string.

EDIT: Look Firebase Functions: Unclear "connection error" to see that even the last line I've pasted has to have await keyword. Otherwise, sometimes you can get an error connection errorbecause of unresolved promises.

来源:https://stackoverflow.com/questions/53415790/firebase-realtime-database-triggers-when-async-and-when-not

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!