Search code examples
javascriptfirebasegoogle-cloud-platformgoogle-cloud-functionsreturn-value

cloud functions firebase return value is always null?


I used cloud function in firebase

function idea is to set leader for the session if there is no leader else return leader's user-id I use javascript

it always returns null even I return snapshot.val or the user id the function receive

console.log(snapshot.val) give me [object Object]

code

exports.SetLeader = functions.https.onCall((data, context) => {
userID = data.ID
sessionID = data.text
sessionref = "/Sessions/".concat(sessionID);
sessionref = sessionref.concat("/Leader");

var db = admin.database();
var ref = db.ref(sessionref);
console.log("ID" + userID)


        ref.once("value", function (snapshot) {
            console.log("snapchot"+ snapshot.val()); //x
            if (snapshot.val() == null) {
                admin.database()
                    .ref(sessionref).update({ userID })
                console.log("inside if " + userID)
                return { leader: userID };
            }else{
               console.log("inside else " + snapshot.val())
                return { leader: snapshot.val()};
            }

        }, function (errorObject) {
            console.log("The read failed: " + errorObject.code);
        });

        });

This is my code

Log if there is no leader, set the new leader and return id log is no leader

Log if there is a leader and I need to return his id Log if there is a leader


Solution

  • As explained in the doc for Callable Cloud Functions, "to return data after an asynchronous operation, return a promise". By using the "callback version" of the once() method, you don't return a Promise.

    You should use the "promise version" as follows:

    return ref.once("value")
            .then(snapshot => {...});
    

    In addition, since you have to deal with different cases, depending on the value of the snapshot, it is more readable to use async/await in your Cloud Function. The following should therefore do the trick (untested):

    exports.SetLeader = functions.https.onCall(async (data, context) => {
    
        try {
            const userID = data.ID
            const sessionID = data.text
            const sessionref = `/Sessions/${sessionID}/Leader`  // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
    
            const db = admin.database();
            const ref = db.ref(sessionref);
            console.log("ID" + userID)
    
            const snapshot = await ref.once("value");
            console.log("snapchot" + snapshot.val());
    
            if (snapshot.val() == null) {
                await admin.database().ref(sessionref).update({ userID })
                console.log("inside if " + userID)
                return { leader: userID };
            } else {
                console.log("inside else " + snapshot.val())
                return { leader: snapshot.val() };
            }
        } catch (error) {
            // See https://firebase.google.com/docs/functions/callable#handle_errors
            // for more fine grained error management
            console.log(error);
            return null;;
        }
    
    });