Agung
Agung

Reputation: 13813

how to set await expression inside a loop in cloud function?

here is my simplified code of my firebase cloud function:

const admin = require("../utilities/firebase_admin_init")
const db = admin.firestore()

exports.cronDeactivatingExpiredEvents = functions.https.onRequest(async (request,response) => {


    const now = new Date()
    const oneMonthAgo = moment().subtract(1,"month").toDate()


    try {
        const expiredEventsSnapshot = await eventRef
        .where("isActive","==",true)
        .where("hasBeenApproved","==",true)
        .where("dateTimeStart",">",oneMonthAgo)
        .where("dateTimeStart","<",now)
        .get()


        const expiredEventIDs = [] // list of IDs here ....


        // prepare promises to delete event data in user 'attendedEvents' subcollection.
        const deleteAttendedEventsDataPromises = []

        for (const eventID of expiredEventIDs) { 

            const eventAttendeeSnapshot = await db.collection("events").doc(eventID).collection("Attendee").get()
            const attendeeDocuments = eventAttendeeSnapshot.docs

            // getting all attendeeIDs.
            const attendeeIDs = []

            attendeeDocuments.forEach( attendeeSnapshot => {
                const attendee = attendeeSnapshot.data()
                attendeeIDs.push(attendee.uid)
            })

            attendeeIDs.forEach( attendeeID => {
                const p = db.collection("users").doc(attendeeID).collection("attendedEvents").doc(eventID).delete()
                deleteAttendedEventsDataPromises.push(p)
            })

        }

        // delete event data in user 'attendedEvents' subcollection
        await Promise.all(deleteAttendedEventsDataPromises)
        console.log(`successfully delete all events data in all attendee user subcollection`)


        response.status(200).send(`sucess`)

    } catch (error) {
        response.status(500).send(error)
    }



})

as you can see above, there is an await expression inside a loop, but I have an error mark like the image below, so I failed to deploy the function:

enter image description here

here is the error after I run firebase deploy

enter image description here

/Users/muchammadagunglaksana/Documents/kumpul_muslim/cloud_functions_serverless_backend/functions/service/cron_operations.js 140:43 error Unexpected await inside a loop no-await-in-loop
170:41 error Unexpected await inside a loop no-await-in-loop

✖ 2 problems (2 errors, 0 warnings)

npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! functions@ lint: eslint . npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the functions@ lint script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in: npm ERR!
/Users/muchammadagunglaksana/.npm/_logs/2019-12-14T10_47_36_788Z-debug.log

Error: functions predeploy error: Command terminated with non-zero exit code1

I have tried to read some solution from here Using async/await with a forEach loop . like using for await like this

enter image description here

indeed that red error mark will dissappear but i still failed to deploy the function. here is the error after I run firebase deploy

enter image description here

functions[cronDeactivatingExpiredEvents(us-central1)]: Deployment error. Function failed on loading user code. Error message: Code in file index.js can't be loaded. Is there a syntax error in your code? Detailed stack trace: /srv/service/cron_operations.js:138 for await (const eventID of algoliaObjectIDs) { // algoliaObjectIDs is same as expired EventIDs ^^^^^

SyntaxError: Unexpected reserved word at createScript (vm.js:80:10) at Object.runInThisContext (vm.js:139:10) at Module._compile (module.js:617:28) at Object.Module._extensions..js (module.js:664:10) at Module.load (module.js:566:32) at tryModuleLoad (module.js:506:12) at Function.Module._load (module.js:498:3) at Module.require (module.js:597:17) at require (internal/module.js:11:18) at Object. (/srv/index.js:2:24)

in .eslintrec.json I use:

"parserOptions": {
    // Required for certain syntax usages
    "ecmaVersion": 2018
  },

I am a new comer in cloud function, and in backend development in general. I am sorry if my question is too basic.

what should I do ?

Upvotes: 2

Views: 1395

Answers (1)

Aritra Chakraborty
Aritra Chakraborty

Reputation: 12542

The first error is regarding eslint there is a rule no-await-in-loop which doesn't allow awaits in loops as the operations are serial, not parallel basically to reduce waste of resource and time.

What you can do is either use it like how you pushed the Promises and then did Promise.all or you can disable the rule for that part only.

/* eslint-disable no-await-in-loop */
for (const eventID of expiredEventIDs) { 

        const eventAttendeeSnapshot = await db.collection("events").doc(eventID).collection("Attendee").get()
        const attendeeDocuments = eventAttendeeSnapshot.docs
        ....
        ....
    }
/* eslint-enable no-await-in-loop */

The second error means that you forgot to wrap the for-await-of in a async function wrapper OR you are using a Node version < 10

Upvotes: 4

Related Questions