0

I am trying to set up (Facebook) Webhook. My databse structure is like this:

{ "users": [
       "1" : {"FacebookID" : "1234567"},
       "2" : {"FacebookID" : "9876554"}
]}

I reduced the code for the webhook to the minimum to show where I have my problems. I go through all entries from the request and check what uid has the change. Before I want to change my data, I would like to see if the user with the id is available in my database. Facebook sends me the FacebookID of course, therefore I need to check, if there is an user account with that specific facebook id.

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

exports.webhooks = functions.https.onRequest((req, res) => {

    var i = 0;
    for (i = 0; i < req.body.entry.length; i++)
    {
        //strCurrentUser = req.body.entry[i].uid;
        strCurrentUser = "2357295025722342"; //For debug

        if (checkIfUserAvailable(strCurrentUser))
        {
            console.log("User is available " + strCurrentUser);
        }
        else 
        {
            console.log("User is not available " + strCurrentUser);
        }
    }

    return res.send(200);
});

function checkIfUserAvailable(userFacebookID)
{
    const rootRef = admin.database().ref();

    return rootRef.child('users').orderByChild('FacebookID').equalTo(userFacebookID).once('value').then( snap =>
    { 
        console.log("snap is : " + (snap.val() !== null));
        return (snap.val() !== null);
    });
}

Now the problem is, that the checkIfUserAvailable always returns true and does not wait till the read is done to return the correct boolean. How can I make sure, that it waits with the return until the read has been finished to get the entire code working?

What I get as result ist:

11:34:58.057 PM / webhooks / snap is : false
11:34:31.665 PM / webhooks / Function execution took 1880 ms, finished with status code: 200
11:34:31.569 PM / webhooks / User is available 2357295025722342
11:34:29.786 PM / webhooks / Function execution started

As you can see the res.send(200) is fired earlier and the snap is: false will be logged later. (I am also not sure why it takes 20 seconds to read data from a almost empty database)

Thanks for the help!

SomehowLuke
  • 69
  • 1
  • 11

1 Answers1

0

You're not using promises correctly. The call to once() is asynchronous and returns immediately before the query is finished. This means the response is sent before the query is done, and Cloud Functions shuts down that async work. Instead, you should be sending that response only after the query is complete.

You might want to watch my videos on using promises in Cloud Functions in order to learn how best to deal with situations like this. Also be sure you understand the documentation.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
  • thanks a lot for your fast response. I am not into JavaScript that much and I was trying to understand that promises but did not get it going for that code. Could you help me with my functions above so I might understand it a bit better. Thanks a lot! – SomehowLuke Oct 06 '18 at 22:02
  • after a long night with no sleep and watching your videos several times I finally got it :-D Thank you for your hints! Finally I understood what promises are for and how to use them, – SomehowLuke Oct 07 '18 at 11:44