1

I have a Firebase Cloud Function that works (it writes to my database as Admin, and also checks for an existing entry with an email string ID). My issue is that it doesn't return the data back to the client app properly.

When I trace the value of result it is {data: null}

I would also like to throw an error if the email exists, but it complains about an unhandled promise (see the comments in the code below).

So there are two questions here. The first being the most pressing.

exports.saveData = functions.https.onCall( (data, context) => {

    // check if the email exists
    admin.database().ref('competition_entries/' + data.compId + '/' + data.emailStringId).once('value').then(function(snapshot) {
        if (snapshot.val() == null){

          console.log("Writing data to "+data.compId+" : "+data.emailStringId);

          let current_datetime = new Date()
          let formatted_time = current_datetime.getHours() + ":" + current_datetime.getMinutes() + ":" + current_datetime.getSeconds();
          let formatted_date = current_datetime.getDate() + "/" + (current_datetime.getMonth() + 1) + "/" + current_datetime.getFullYear();
          let timestamp_string = formatted_time+" "+formatted_date;
          console.log(formatted_date)

          admin.database().ref('competition_entries/' + data.compId + '/' + data.emailStringId).set({
            name: data.name,
            email: data.email,
            phone: data.phone,
            selectedItem: data.selectedItem,
            submitted_date: timestamp_string
          })
          .then(() => {
            console.log("success");
            return {
              "error": "none",
              "message": "success"
            };
          }).catch(function(error) {
            throw error;
          });

        }else{
            // email address exists as a data entry so tell the user that they have already submitted
            let code = "already-exists";
            let message = "Email address already exists";
            let details = "A user with the same email address has already entered the competition.";
            console.log(message+"/"+details);

            /*
              TODO: throwing an HttpsError directly here was causing an unresolved promise error. This would be the better way to tell the client that the user has already submitted their data.
            */
            // throw error;
            //throw new functions.https.HttpsError(code, message, details);

            // this resolves the promise error but is a hack
            return {
              error: new functions.https.HttpsError(code, message, details),
              message: message
            }
        }
    }).catch(function(error) {
      throw error;
    });
});

1 Answer 1

3

I think the problem is you are not returning enough. Functions needs every function to return something to execute succesfully.

Commonly is return true or return Promise

So it should be something like this:

//check if email exist
return admin.databse...

    //If there is no user create it
     return.admin...

The code does write the database but since it was no return that happened asynchronously, and the code would keep executing from top to bottom making the function to response jibberish to the client.

You should

  • if (!snapshot) shortcircuiting is better because snapshot could be undefined causing an exception when checkinf if snapshot data is null
  • You dont need to use the admin sdk for the database, Functions is considered a trusted enviroments so operations are runned with admin privileges. You can CRUD anything despite rules or user restrictions
Sign up to request clarification or add additional context in comments.

2 Comments

I just discovered the bit about adding 'return' but thanks for the other tips too! Appreciate it.
My problem now is that I deployed it and I get a CORS issue. Any tips?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.