Firebase realtime database triggers: When async and when not
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.
node.js firebase firebase-realtime-database google-cloud-functions
add a comment |
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.
node.js firebase firebase-realtime-database google-cloud-functions
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
add a comment |
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.
node.js firebase firebase-realtime-database google-cloud-functions
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.
node.js firebase firebase-realtime-database google-cloud-functions
node.js firebase firebase-realtime-database google-cloud-functions
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
add a comment |
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
add a comment |
1 Answer
1
active
oldest
votes
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 (
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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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 (
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
add a comment |
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 (
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
add a comment |
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 (
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 (
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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