-1

So, I am using the Facebook JavaScript SDK to allow users to login to my app. I am using the Facebook SDK in an HTML file along with another JavaScript file. The second JS file accesses the FB object from inside the SDK. The HTML is basically set up like so

<!DOCTYPE HTML>
<html>
     <body>
          <script src = 'FacebookSDK.js' type = 'text/javascript'></script>
    </body>
          <script src = 'Controller.js' type = 'text/javascript'></script>
</html>

When I try to access the FB object inside the Controller.js file like so

            FB.getLoginStatus(function(response) {
                console.log(response.authResponse.userID);
            });

I get an error saying

pollcreationClient.js:4 Uncaught ReferenceError: FB is not defined

So, clearly my Controller.js file is executing before the Facebook SDK has initialized. I thought setting the second JS file to load outside the body tag would provide enough time for the SDK to load and initialize. But, this clearly isn't the case. What do I do to make sure that my Controller.js file function, where I call the FB object, doesn't execute until the SDK file has finished executing?

For reference, here is the Facebook SDK file

// This is called with the results from from FB.getLoginStatus().
    function statusChangeCallback(response) {
        console.log('statusChangeCallback');
        console.log(response);

        // The response object is returned with a status field that lets the
        // app know the current login status of the person.
        // Full docs on the response object can be found in the documentation
        // for FB.getLoginStatus().
        if (response.status === 'connected') {
            // Logged into your app and Facebook.
            testAPI();
        }
        else if (response.status === 'not_authorized') {
            // The person is logged into Facebook, but not your app.
            document.getElementById('status').innerHTML = 'Please log ' +
                'into this app.';
        }
        else {
            // The person is not logged into Facebook, so we're not sure if
            // they are logged into this app or not.
            document.getElementById('status').innerHTML = 'Please log ' +
                'into Facebook.';
        }
    }

    // This function is called when someone finishes with the Login
    // Button.  See the onlogin handler attached to it in the sample
    // code below.
    function checkLoginState() {
        FB.getLoginStatus(function(response) {
            statusChangeCallback(response);
        });
    }

    window.fbAsyncInit = function() {
        FB.init({
            appId: '332044557128106',
            cookie: true, // enable cookies to allow the server to access 
            // the session
            xfbml: true, // parse social plugins on this page
            version: 'v2.5' // use graph api version 2.5
        });

        // Now that we've initialized the JavaScript SDK, we call 
        // FB.getLoginStatus().  This function gets the state of the
        // person visiting this page and can return one of three states to
        // the callback you provide.  They can be:
        //
        // 1. Logged into your app ('connected')
        // 2. Logged into Facebook, but not your app ('not_authorized')
        // 3. Not logged into Facebook and can't tell if they are logged into
        //    your app or not.
        //
        // These three cases are handled in the callback function.

        FB.getLoginStatus(function(response) {
            statusChangeCallback(response);
        });

    };

    // Load the SDK asynchronously
    (function(d, s, id) {
        var js, fjs = d.getElementsByTagName(s)[0];
        if (d.getElementById(id)) return;
        js = d.createElement(s);
        js.id = id;
        js.src = "//connect.facebook.net/en_US/sdk.js";
        fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'facebook-jssdk'));

    // Here we run a very simple test of the Graph API after login is
    // successful.  See statusChangeCallback() for when this call is made.
    function testAPI() {
        console.log('Welcome!  Fetching your information.... ');
        FB.api('/me', function(response) {
            console.log('Successful login for: ' + response.name);
            document.getElementById('status').innerHTML =
                'Thanks for logging in, ' + response.name + '!';
        });
    }
andyrandy
  • 72,880
  • 8
  • 113
  • 130
random_coder_101
  • 1,782
  • 3
  • 24
  • 50
  • how about window.FB? – Mehrad Sep 27 '16 at 19:26
  • is facebook.js even loading? Also shouldn't have script after closing body tag..put it inside – charlietfl Sep 27 '16 at 19:29
  • @darham - what about window.FB? Does that mean that the window.FB function will only execute when there is a FB object detected in the window? – random_coder_101 Sep 27 '16 at 19:32
  • look for a global object that is in the window instance, also why not put your script inside the body tag? – Mehrad Sep 27 '16 at 19:33
  • @charlietfl - Yeah, facebook.js is loading, it eventually logs all the statements its supposed to. But, not until the second JS file executes. Why should I not have it outside of the closing body tag? What's wrong with that? – random_coder_101 Sep 27 '16 at 19:34
  • @darham - Yeah, I moved the script back inside of the body tag. But, it doesn't make any difference. The reason I left it out of the body tags was because I figured that would allow the Facebook SDK to load before calling the second JS file. – random_coder_101 Sep 27 '16 at 19:36
  • add a load event listener for your appended script tag `js.onload=function(){ /* init here */};` – charlietfl Sep 27 '16 at 19:40
  • @charlietfl - Can you explain that in a little more detail? – random_coder_101 Sep 27 '16 at 19:44
  • simple...you opted to load the sdk async so you now have to wait for it to load before you can use it – charlietfl Sep 27 '16 at 19:49
  • 1
    The fbAsyncInit callback is the ONLY reliable way to know when the FB SDK is initialized. not sure why you are doing what you are doing... – andyrandy Sep 27 '16 at 19:52
  • btw, there is also a synchronous way to load the js sdk, i think. not recommended though. you better just call a function of controller.js in fbAsyncInit, to start whatever you want to start. – andyrandy Sep 27 '16 at 19:54
  • @luschn - Because I am reusing the Facebook SDK in multiple HTML files to get access to the response object from it. I can't name any functions within the SDK file itself because those might exist in some JavaScript files while they may not exist in others. – random_coder_101 Sep 27 '16 at 20:26
  • @charlietfl - So how exactly would that work with the jquery onload? Would it just be window.fbAsyncInit.on('load', function(){})? – random_coder_101 Sep 27 '16 at 20:28
  • since you need this right way...why are you wanting to load the sdk async in the first place? if you put it in it's own script tag you wouldn't have any issues – charlietfl Sep 27 '16 at 20:32
  • why would you use jquery onload? that does not solve your problem. dont use jquery if you are not 100% sure you NEED it. which is almost never the case, and the question is not related to jquery anyway. – andyrandy Sep 27 '16 at 20:46
  • we dont know how your controller.js looks like, but in general it is a good idea to put the facebook sdk stuff into that file, where you can control what happens and when. – andyrandy Sep 27 '16 at 20:50
  • You could could always put your own function at the end of the `window.fbAsyncInit` function in the SDK file - this way, you are working in the same form that the FB SDK file works. – Derek Pollard Sep 27 '16 at 21:06

1 Answers1

0

I found a quick workaround to my problem. NOTE: It doesn't provide a perfect solution, more of a patchwork job. I didn't use the solutions mentioned in the comments because they didn't work in my situation. Hopefully this might be useful to someone else.

Found this answer here How to workaround 'FB is not defined'?

if (typeof FB !== 'undefined' && FB !== null) {
            FB.Event.subscribe('auth.authResponseChange', function() {
                FB.getLoginStatus(function(response) {
                    console.log('Response from in here');
                    console.log(response);
                    $('.submit-butt').on('click', function() {
                        console.log('From in here');
                        ajaxFunctions.ready(ajaxFunctions.ajaxRequest('POST', appUrl + '/poll-create', response.authResponse, function(data) {

                        }));
                    });
                });
            });
        }else{
            location.reload();
        }

Basically, this checks whether the FB object is defined and exists. If it does, it runs the code and if it doesn't I've set the page to reload. This works for me because my issue was that it was in certain situations where the FB object was not being defined, whereas it worked at other times. Again, this is not a great solution but it does the job for me.

Community
  • 1
  • 1
random_coder_101
  • 1,782
  • 3
  • 24
  • 50