Async Script Loading and FB SDK

For yet another web app, that requires a Facebook OAuth login, I deviated from FB’s code examples and bumped into a race condition!

$#@! happens

  1. My code:
    <script>
    window.fbAsyncInit=function(){
    	FB.init({appId:'verylongnumber',cookie:true,version:'v2.0',...});
    };
    </script>
    <script src="//connect.facebook.net/en_US/sdk.js"></script>

    Reportedly, sdk.js calls fbAsyncInit “after everything is setup[…] and calls made within this function will guarantee the existence of the FB object”, which I’m using later:

    $(function(){
    	window.check_login_status=function(){
    		FB.getLoginStatus(function(r){
    
  2. But, race condition! — browser sometimes triggered jQuery’s ready() before the SDK script executed/finished. I’d occasionally get a warning (should be an error!) in the console: “FB.getLoginStatus() called before calling FB.init() — sdk.js:53”. It’s possible to even encounter “FB is undefined” errors.
  3. FB’s example code “avoided dealing” with this by dynamically injecting the SDK script, presumably causing a CSSOM block, so sdk.js won’t run before… what? But even this doesn’t work reliably!
    // 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'));
  4. So, hey, if it works, why am I rocking the boat? Because Ilya Grigorik writes (comprehensively!) in Script-injected “async scripts” considered harmful: “inline scripts block on CSSOM”, causing performance degradation. We sure don’t want to mess with CSS related performance.

“Hack-around”

  1. I chained loading sdk.js to guarantee it never calling fbAsyncInit before jQuery’s ready fires. Disgusting.

Solution?

  1. My code wants to manipulate the DOM, page transitions and stuff, and depends on both DOM ready and the FB.getLoginStatus AJAX response. How to register one callback for two unordered events?



Comments are closed.