Reputation: 2538
I'm trying to do a relatively simple, in theory, function using Firebase Functions.
Specifically:
Add + 1
to a realtime database variable for all users
Send a notification to all users
I'm still trying to understand async
/await
which is probably why I'm struggling so much with this.
Here is what I'm doing:
exports.gcIncrement = functions.database
.ref('gthreads/{threadId}/messages/{messageId}')
.onCreate(async (snapshot, context) => {
const data = snapshot.val();
const threadId = context.params.threadId;
const uid = context.auth.uid;
adb.ref('gchats/' + threadId).once('value').then(async (gchatData) => {
const parent = gchatData.val();
incrementUser(parent.users, uid, threadId); //parent.users is an object with 1-30 users.
sendGCNotification(parent.users, data);
return true;
}).catch(error => console.log(error))
});
And then I have the function incrementUser
:
function IncrementUser(array, uid, threadId) {
for (const key in array) {
if (key != uid) {
const gcMessageRef =
adb.ref('users/' + key + '/gthreads/' + threadId + '/' + threadId+'/unread/');
gcMessageRef.transaction((int) => {
return (int || 0) + 1;
}
}
}
and the function sendGCNotification
:
function sendGCNotification(array, numbOfMsg, data) {
let payload = {
notification: {
title: 'My App - ' + data.title,
body: "This is a new notification!",
}
}
const db = admin.firestore()
for (const key in array) {
if (!data.adminMessage) {
if (array[key] === 0) {
const devicesRef = db.collection('devices').where('userId', '==', key)
const devices = await devicesRef.get();
devices.forEach(result => {
const tokens = [];
const token = result.data().token;
tokens.push(token)
return admin.messaging().sendToDevice(tokens, payload)
})
}
}
}
}
I currently get the error:
'await' expression is only allowed within an async function.
const devices = await devicesRef.get();
But even when I get it error-free, it doesn't seem work. The Firebase Functions log says:
4:45:26.207 PM gcIncrement Function execution took 444 ms, finished with status: 'ok' 4:45:25.763 PM gcIncrement Function execution started
So it seems to run as expected but not fulfill the code as expected. Any ideas? Thank you!
Upvotes: 2
Views: 1257
Reputation: 317948
All uses of await
have to occur within the main body of a function that's marked async
. Your function sendGCNotification
is not async. You'll have to mark it async, and also make sure that any promises within it have been awaited, or return a promise that resolves when all the async work is done.
Also, in IncrementUser
you are not handling the promise returned by gcMessageRef.transaction(). You need to handle every promise that you generate from all the async work, and make sure they are all a part of the final promise that you return or await from your top-level function.
If you want to learn more about promises and async/await in Cloud Functions code, I suggest you use my video series. Specifically, the one titled "How does async/await work with TypeScript and ECMAScript 2017?". Even if you aren't using TypeScript, async/await work the same way.
Upvotes: 4