How to detect when facebook's FB.init is complete

后端 未结 12 1976
我寻月下人不归
我寻月下人不归 2020-11-28 01:28

The old JS SDK had a function called FB.ensureInit. The new SDK does not seem to have such function... how can I ensure that I do not make api calls until it is fully initia

相关标签:
12条回答
  • 2020-11-28 01:54

    The Facebook API watches for the FB._apiKey so you can watch for this before calling your own application of the API with something like:

    window.fbAsyncInit = function() {
      FB.init({
        //...your init object
      });
      function myUseOfFB(){
        //...your FB API calls
      };
      function FBreadyState(){
        if(FB._apiKey) return myUseOfFB();
        setTimeout(FBreadyState, 100); // adjust time as-desired
      };
      FBreadyState();
    }; 
    

    Not sure this makes a difference but in my case--because I wanted to be sure the UI was ready--I've wrapped the initialization with jQuery's document ready (last bit above):

      $(document).ready(FBreadyState);
    

    Note too that I'm NOT using async = true to load Facebook's all.js, which in my case seems to be helping with signing into the UI and driving features more reliably.

    0 讨论(0)
  • 2020-11-28 01:55

    Here is a solution in case you use jquery and Facebook Asynchronous Lazy Loading:

    // listen to an Event
    $(document).bind('fbInit',function(){
        console.log('fbInit complete; FB Object is Available');
    });
    
    // FB Async
    window.fbAsyncInit = function() {
        FB.init({appId: 'app_id', 
             status: true, 
             cookie: true,
             oauth:true,
             xfbml: true});
    
        $(document).trigger('fbInit'); // trigger event
    };
    
    0 讨论(0)
  • 2020-11-28 01:55

    I've avoided using setTimeout by using a global function:

    EDIT NOTE: I've updated the following helper scripts and created a class that easier/simpler to use; check it out here ::: https://github.com/tjmehta/fbExec.js

    window.fbAsyncInit = function() {
        FB.init({
            //...
        });
        window.fbApiInit = true; //init flag
        if(window.thisFunctionIsCalledAfterFbInit)
            window.thisFunctionIsCalledAfterFbInit();
    };
    

    fbEnsureInit will call it's callback after FB.init

    function fbEnsureInit(callback){
      if(!window.fbApiInit) {
        window.thisFunctionIsCalledAfterFbInit = callback; //find this in index.html
      }
      else{
        callback();
      }
    }
    

    fbEnsureInitAndLoginStatus will call it's callback after FB.init and after FB.getLoginStatus

    function fbEnsureInitAndLoginStatus(callback){
      runAfterFbInit(function(){
        FB.getLoginStatus(function(response){
          if (response.status === 'connected') {
            // the user is logged in and has authenticated your
            // app, and response.authResponse supplies
            // the user's ID, a valid access token, a signed
            // request, and the time the access token
            // and signed request each expire
            callback();
    
          } else if (response.status === 'not_authorized') {
            // the user is logged in to Facebook,
            // but has not authenticated your app
    
          } else {
            // the user isn't logged in to Facebook.
    
          }
        });
      });
    }
    

    fbEnsureInit example usage:

    (FB.login needs to be run after FB has been initialized)

    fbEnsureInit(function(){
        FB.login(
           //..enter code here
        );
    });
    

    fbEnsureInitAndLogin example usage:

    (FB.api needs to be run after FB.init and FB user must be logged in.)

    fbEnsureInitAndLoginStatus(function(){
        FB.api(
           //..enter code here
        );
    });
    
    0 讨论(0)
  • 2020-11-28 01:57

    Here's a simpler method, that requires neither events or timeouts. It does require jQuery, however.

    Use jQuery.holdReady() (docs)

    So, immediately after your jQuery script, delay the ready event.

    <!-- jQuery -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <script>
        $.holdReady( true ); // don't fire ready until told (ie when FB loaded)
    </script>
    

    Then, in your Facebook init function, release it:

    window.fbAsyncInit = function() {
        FB.init({
            appId: '11111111111111',
            cookie: true,
            xfbml: false,
            version: 'v2.4'
        });
    
        // release the ready event to execute
        $.holdReady( false );
    };
    

    Then you can use the ready event as normal:

    $(document).ready( myApp.init );
    
    0 讨论(0)
  • 2020-11-28 01:59

    Instead of using any setTimeout or setInterval I would stick to deferred objects (implementation by jQuery here). It's still tricky to resolve queue in proper moment, because init don't have callbacks but combining result with event subscription (as someone pointed before me), should do the trick and be close enough.

    Pseudo-snippet would look as follows:

    FB.Event.subscribe('auth.statusChange', function(response) {
       if (response.authResponse) {
           // user has auth'd your app and is logged into Facebook
       } else {
           // user has not auth'd your app, or is not logged into Facebook
       }
       DeferredObject.resolve();
    });
    
    0 讨论(0)
  • 2020-11-28 02:06

    Another way to check if FB has initialized is by using the following code:

    ns.FBInitialized = function () {
        return typeof (FB) != 'undefined' && window.fbAsyncInit.hasRun;
    };
    

    Thus in your page ready event you could check ns.FBInitialized and defer the event to later phase by using setTimeOut.

    0 讨论(0)
提交回复
热议问题