Aldo Manuel Gonzalez
Aldo Manuel Gonzalez

Reputation: 95

Firebase cloud function finished before complete the foreach

I want to update the list of "Reservations" with some new variables. But I can't make it work because the function ends before updating. I know the problem is because I make asynchronous calls but I can't solve it. How can I use Promise in this case?

I edited the code using Promise but still does not update the "Reservations" Returns {"data": null} to my website console In the firebase console does not generate any errors. Return the message "reservations actualized"

exports.actualizeReservations = functions.https.onCall((data, response) => {
var promisesUpdateReservations = [];
return admin.database().ref(Constants.RESERVATIONS).once("value")
.then((snapshot) => {
    console.log("RESERVATIONS: " + snapshot)
    snapshot.forEach((reserveSnap) => {
        var reserve = reserveSnap.val();
        if(reserve.reservationId && reserve.restoId) {
            admin.database().ref(`${Constants.RESTAURANTS}/${reserve.restoId}`).once("value")
            .then((restoSnap) => {
                if(restoSnap.exists() && restoSnap.val() !== null) {
                    var resto = restoSnap.val();
                    if(resto.address && !resto.address.fullAddress) {
                        var restoAddress = resto.address ? {
                            street: resto.address.street ? resto.address.street : "",
                            fullAddress: resto.address.fullAddress ? resto.address.fullAddress : "",
                            city: resto.address.city ? resto.address.city : "",
                            country: resto.address.country ? resto.address.country : "",
                            postalCode: resto.address.postalCode ? resto.address.postalCode : "",
                            province: resto.address.province ? resto.address.province : "",
                            l: resto.l ? resto.l : null,
                            g: resto.g ? resto.g : null,
                        } : null;
                        var restoUserIDs = `${reserve.restoId}/${reserve.userId}`;
                        const promiseUpdateReservation = admin.database().ref(`${Constants.RESERVATIONS}/${reserve.reservationId}`).update({
                            restoAddress,
                            restoUserIDs
                        })
                        promisesUpdateReservations.push(promiseUpdateReservation)
                    }
                }
            })
            .catch((err) => {
                console.log("resto not found")
            });
        }
    });
    Promise.all(promisesUpdateReservations)
    .then(() => {
        console.log("reservations actualized");
        return { code: 0, result: "successful", description: "reservations actualized" };
    })
})
.catch((err) => {
    console.log("get restaurants error: " + err);
    return { code: 1, result: "successful", description: "reservations not loaded" };;
});
})

Upvotes: 2

Views: 220

Answers (1)

Doug Stevenson
Doug Stevenson

Reputation: 317372

This function is going to complete immediately every time it's invoke, and likely perform none of its work. This is because it's not returning anything at all from the top-level function callback. Instead, you need to return a promise from the top level of the function that resolves with the data to send to the client only after all the async work is complete (and you're kicking off a lot of it here). Proper handling of promises is critical to making Cloud Functions work correctly.

Upvotes: 2

Related Questions