问题
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 error
because of unresolved promises.
来源:https://stackoverflow.com/questions/53415790/firebase-realtime-database-triggers-when-async-and-when-not