1
votes

I am trying to write and deploy a firebase CF to listen to document creation in 'posts' collection and send notifications. Below is the function I wrote.

const functions = require('firebase-functions');
const db = admin.firestore();

//

exports.myFunction = functions.firestore
.document('posts').onCreate((snap,context) => {
    const postdata = snap.data();
    const postid = postdata.postid;
    return db.collection('subscription').doc(postid).get()
    .then(doc=>{
        const subsuid = doc.data().subs_uid;
        subsuid.forEach(sb=>{
            const tokendata = (await db.collection('tokens').doc(sb).get()).data();
            await admin.messaging().sendMulticast(
                {
                    tokens:tokendata.token, // ['token_1', 'token_2', ...]
                    notification: {
                        title: 'title',
                        body: 'text'
                    },
                    apns: {
                        headers: {
                            'apns-priority': '10',
                        },
                        payload: {
                            aps: {
                                contentAvailable: true
                            }
                        }
                    },
                    android: {
                        priority: 'high',
                    }
                }
            );
        })
    })
})

However, when I try to deploy the function, the system returns below error:

Error: Error occurred while parsing your function triggers.

/path_to_my_function
            const tokendata = (await db.collection('tokens').doc(sb).get()).data();
                                    ^^

SyntaxError: Unexpected identifier
    at wrapSafe (internal/modules/cjs/loader.js:1053:16)
    at Module._compile (internal/modules/cjs/loader.js:1101:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1157:10)
    at Module.load (internal/modules/cjs/loader.js:985:32)
    at Function.Module._load (internal/modules/cjs/loader.js:878:14)
    at Module.require (internal/modules/cjs/loader.js:1025:19)
    at require (internal/modules/cjs/helpers.js:72:18)
    at /usr/local/lib/node_modules/firebase-tools/lib/triggerParser.js:15:15
    at Object.<anonymous> (/usr/local/lib/node_modules/firebase-tools/lib/triggerParser.js:53:3)
    at Module._compile (internal/modules/cjs/loader.js:1137:30)

Don't know where I went wrong, because all the other functions are deployed and run without any problem, and the await command in this case doesn't seem wrong.

Can someone advise on what might be the root cause of this?

1
While someone fleshes out a complete answer, some food for thought and to point you in the right direction: await is only recognised within functions that are declared with async. forEach is often misused in chained Promises and map should be used together with Promise.all instead.samthecodingman

1 Answers

0
votes

Inspired by @samthecodingman 's comment, I edited the code and the below code works just fine. Thanks!

exports.myFunction = functions.firestore
.document('posts').onCreate((snap,context) => {
    const postdata = snap.data();
    const postid = postdata.postid;
    return db.collection('subscription').doc(postid).get()
    .then(doc=>{
        const subsuid = doc.data().subs_by_users_uid;
        const qSubsuid = subsuid.map(sb=>db.collection('tokens').doc(sb).get());
        return Promise.all(qSubsuid)
        .then(results=>{
            results.forEach(doc=>{
                return admin.messaging().sendMulticast(
                    {
                        tokens:doc.data().token, // ['token_1', 'token_2', ...]
                        notification: {
                            title: 'title',
                            body: 'body'
                        },
                        apns: {
                            headers: {
                                'apns-priority': '10',
                            },
                            payload: {
                                aps: {
                                    contentAvailable: true
                                }
                            }
                        },
                        android: {
                            priority: 'high',
                        }
                    }
                );
            })
        })   
    })
})