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

Update on Jan 04, 2012

It seems like you can't just call FB-dependent methods (for example FB.getAuthResponse()) right after FB.init() like before, as FB.init() seems to be asynchronous now. Wrapping your code into FB.getLoginStatus() response seems to do the trick of detecting when API is fully ready:

window.fbAsyncInit = function() {
    FB.init({
        //...
    });

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

};  

or if using fbEnsureInit() implementation from below:

window.fbAsyncInit = function() {
    FB.init({
        //...
    });

    FB.getLoginStatus(function(response){
        fbApiInit = true;
    });

};  

Original Post:

If you want to just run some script when FB is initialized you can put some callback function inside fbAsyncInit:

  window.fbAsyncInit = function() {
    FB.init({
      appId  : '<?php echo $conf['fb']['appid']; ?>',
      status : true, // check login status
      cookie : true, // enable cookies to allow the server to access the session
      xfbml  : true  // parse XFBML
    });
    FB.Canvas.setAutoResize();

    runFbInitCriticalCode(); //function that contains FB init critical code
  };

If you want exact replacement of FB.ensureInit then you would have to write something on your own as there is no official replacement (big mistake imo). Here is what I use:

  window.fbAsyncInit = function() {
    FB.init({
      appId  : '<?php echo $conf['fb']['appid']; ?>',
      status : true, // check login status
      cookie : true, // enable cookies to allow the server to access the session
      xfbml  : true  // parse XFBML
    });
    FB.Canvas.setAutoResize();

    fbApiInit = true; //init flag
  };

  function fbEnsureInit(callback) {
        if(!window.fbApiInit) {
            setTimeout(function() {fbEnsureInit(callback);}, 50);
        } else {
            if(callback) {
                callback();
            }
        }
    }

Usage:

fbEnsureInit(function() {
    console.log("this will be run once FB is initialized");
});

Actually Facebook has already provided a mechanism to subscribe to authentication events.

In your case you are using "status: true" which means that FB object will request Facebook for user's login status.

FB.init({
    appId  : '<?php echo $conf['fb']['appid']; ?>',
    status : true, // check login status
    cookie : true, // enable cookies to allow the server to access the session
    xfbml  : true  // parse XFBML
});

By calling "FB.getLoginStatus()" you are running the same request again.

Instead you could use FB.Event.subscribe to subscribe to auth.statusChange or auth.authResponseChange event BEFORE you call FB.init

FB.Event.subscribe('auth.statusChange', function(response) {
    if(response.status == 'connected') {
        runFbInitCriticalCode();
    }
});

FB.init({
    appId  : '<?php echo $conf['fb']['appid']; ?>',
    status : true, // check login status
    cookie : true, // enable cookies to allow the server to access the session
    xfbml  : true  // parse XFBML
});

Most likely, when using "status: false" you can run any code right after FB.init, because there will be no asynchronous calls.


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
};