Firebase realtime database triggers: When async and when not












1















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:
enter image description here
for the case without async,
and enter image description here
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.










share|improve this question

























  • The async keyword on a function just tells JavaScript that you are intending to return a promise from that function that resolves when all the pending work in that function is complete. Learn more about how to correctly deal with promises in Cloud Functions using my video tutorial series. firebase.google.com/docs/functions/video-series

    – Doug Stevenson
    Nov 21 '18 at 20:26


















1















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:
enter image description here
for the case without async,
and enter image description here
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.










share|improve this question

























  • The async keyword on a function just tells JavaScript that you are intending to return a promise from that function that resolves when all the pending work in that function is complete. Learn more about how to correctly deal with promises in Cloud Functions using my video tutorial series. firebase.google.com/docs/functions/video-series

    – Doug Stevenson
    Nov 21 '18 at 20:26
















1












1








1


1






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:
enter image description here
for the case without async,
and enter image description here
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.










share|improve this question
















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:
enter image description here
for the case without async,
and enter image description here
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.







node.js firebase firebase-realtime-database google-cloud-functions






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 21 '18 at 17:45







Ilonpilaaja

















asked Nov 21 '18 at 15:51









IlonpilaajaIlonpilaaja

317214




317214













  • The async keyword on a function just tells JavaScript that you are intending to return a promise from that function that resolves when all the pending work in that function is complete. Learn more about how to correctly deal with promises in Cloud Functions using my video tutorial series. firebase.google.com/docs/functions/video-series

    – Doug Stevenson
    Nov 21 '18 at 20:26





















  • The async keyword on a function just tells JavaScript that you are intending to return a promise from that function that resolves when all the pending work in that function is complete. Learn more about how to correctly deal with promises in Cloud Functions using my video tutorial series. firebase.google.com/docs/functions/video-series

    – Doug Stevenson
    Nov 21 '18 at 20:26



















The async keyword on a function just tells JavaScript that you are intending to return a promise from that function that resolves when all the pending work in that function is complete. Learn more about how to correctly deal with promises in Cloud Functions using my video tutorial series. firebase.google.com/docs/functions/video-series

– Doug Stevenson
Nov 21 '18 at 20:26







The async keyword on a function just tells JavaScript that you are intending to return a promise from that function that resolves when all the pending work in that function is complete. Learn more about how to correctly deal with promises in Cloud Functions using my video tutorial series. firebase.google.com/docs/functions/video-series

– Doug Stevenson
Nov 21 '18 at 20:26














1 Answer
1






active

oldest

votes


















0














I have a very similar issue that I can't get past the Functions parser.



exports.triggerInvoiceCreate = functions.firestore
.document('accounts/{businessId}/projects/{projectId}')
.onUpdate(async (change, context) => {
try {
const businessId = context.params.businessId
const project = change.after.data()

const clientRef = await admin
.firestore()
.doc(`accounts/${businessId}/clients/${project.client.id}`)
.get()
const client = clientRef.data()
return Promise.resolve(client)
} catch (error) {
console.log(error)
return Promise.reject(error)
}
})


I have no idea why I'm getting:



Detailed stack trace: /user_code/index.js:23
.onUpdate(async (change, context) => {
^
SyntaxError: Unexpected token (





share|improve this answer
























  • Nevermind, I was using the default Node version (6) - so after adding to my package.json: engines: { "node": "8" } I didn't get this error anymore. :)

    – joelataylor
    Jan 2 at 15:34













Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53415790%2ffirebase-realtime-database-triggers-when-async-and-when-not%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














I have a very similar issue that I can't get past the Functions parser.



exports.triggerInvoiceCreate = functions.firestore
.document('accounts/{businessId}/projects/{projectId}')
.onUpdate(async (change, context) => {
try {
const businessId = context.params.businessId
const project = change.after.data()

const clientRef = await admin
.firestore()
.doc(`accounts/${businessId}/clients/${project.client.id}`)
.get()
const client = clientRef.data()
return Promise.resolve(client)
} catch (error) {
console.log(error)
return Promise.reject(error)
}
})


I have no idea why I'm getting:



Detailed stack trace: /user_code/index.js:23
.onUpdate(async (change, context) => {
^
SyntaxError: Unexpected token (





share|improve this answer
























  • Nevermind, I was using the default Node version (6) - so after adding to my package.json: engines: { "node": "8" } I didn't get this error anymore. :)

    – joelataylor
    Jan 2 at 15:34


















0














I have a very similar issue that I can't get past the Functions parser.



exports.triggerInvoiceCreate = functions.firestore
.document('accounts/{businessId}/projects/{projectId}')
.onUpdate(async (change, context) => {
try {
const businessId = context.params.businessId
const project = change.after.data()

const clientRef = await admin
.firestore()
.doc(`accounts/${businessId}/clients/${project.client.id}`)
.get()
const client = clientRef.data()
return Promise.resolve(client)
} catch (error) {
console.log(error)
return Promise.reject(error)
}
})


I have no idea why I'm getting:



Detailed stack trace: /user_code/index.js:23
.onUpdate(async (change, context) => {
^
SyntaxError: Unexpected token (





share|improve this answer
























  • Nevermind, I was using the default Node version (6) - so after adding to my package.json: engines: { "node": "8" } I didn't get this error anymore. :)

    – joelataylor
    Jan 2 at 15:34
















0












0








0







I have a very similar issue that I can't get past the Functions parser.



exports.triggerInvoiceCreate = functions.firestore
.document('accounts/{businessId}/projects/{projectId}')
.onUpdate(async (change, context) => {
try {
const businessId = context.params.businessId
const project = change.after.data()

const clientRef = await admin
.firestore()
.doc(`accounts/${businessId}/clients/${project.client.id}`)
.get()
const client = clientRef.data()
return Promise.resolve(client)
} catch (error) {
console.log(error)
return Promise.reject(error)
}
})


I have no idea why I'm getting:



Detailed stack trace: /user_code/index.js:23
.onUpdate(async (change, context) => {
^
SyntaxError: Unexpected token (





share|improve this answer













I have a very similar issue that I can't get past the Functions parser.



exports.triggerInvoiceCreate = functions.firestore
.document('accounts/{businessId}/projects/{projectId}')
.onUpdate(async (change, context) => {
try {
const businessId = context.params.businessId
const project = change.after.data()

const clientRef = await admin
.firestore()
.doc(`accounts/${businessId}/clients/${project.client.id}`)
.get()
const client = clientRef.data()
return Promise.resolve(client)
} catch (error) {
console.log(error)
return Promise.reject(error)
}
})


I have no idea why I'm getting:



Detailed stack trace: /user_code/index.js:23
.onUpdate(async (change, context) => {
^
SyntaxError: Unexpected token (






share|improve this answer












share|improve this answer



share|improve this answer










answered Jan 2 at 6:26









joelataylorjoelataylor

1201212




1201212













  • Nevermind, I was using the default Node version (6) - so after adding to my package.json: engines: { "node": "8" } I didn't get this error anymore. :)

    – joelataylor
    Jan 2 at 15:34





















  • Nevermind, I was using the default Node version (6) - so after adding to my package.json: engines: { "node": "8" } I didn't get this error anymore. :)

    – joelataylor
    Jan 2 at 15:34



















Nevermind, I was using the default Node version (6) - so after adding to my package.json: engines: { "node": "8" } I didn't get this error anymore. :)

– joelataylor
Jan 2 at 15:34







Nevermind, I was using the default Node version (6) - so after adding to my package.json: engines: { "node": "8" } I didn't get this error anymore. :)

– joelataylor
Jan 2 at 15:34




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53415790%2ffirebase-realtime-database-triggers-when-async-and-when-not%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Wiesbaden

Marschland

Dieringhausen