26.9.12

Asynchronous library loading with jQuery.Deferred

A common pattern for asynchronous library loading, without the use of script loaders (requirejs, etc).
var your_library = 'can be FB (facebook) or google or whatever';

jQuery.when (window[your_library] || jQuery.Deferred (function(loader){
  load(your_library);
  loader.resolve();
}))
.done (do_stuff);

function load (){
  /* append the script to the page and declare the callback */
}

function do_stuff(){
/* continue, assuming that window[your_library] is loaded */
}

Example Using Facebook API

jQuery.when (window['FB'] || jQuery.Deferred (function(loader){

  // 1. load the Facebook API
  jQuery('<div id=fb-root></div>\
    <script src="//connect.facebook.net/en_US/all.js" async></script>')
    .appendTo('body');

  // 2. the Facebook API has a default callback function name
  window.fbAsyncInit = function(){

    // ensure this is run only once
    window.fbAsyncInit = Function;

    FB.init({/* your init parameters here */});

    // 3a. trigger the continuation of the script
    loader.resolve();
  };
}))
// 3b. continue
.done(function(){
  FB.getLoginStatus(function(response){
    /* etc. */
  });
});
The pattern is simple. If the library in question has already loaded, it simply continues straight to done, otherwise it will call the deferred loader.

Example Using Google Maps API

jQuery.when(window['google'] || jQuery.Deferred(function(loader){    
  // a unique callback function name because why not
  var callback = '_' + (+new Date).toString(36),
      // use your key here if you need it
      src = '//maps.googleapis.com/maps/api/js?sensor=true&callback='
          + callback;

  // 1. load google maps
  $('<script>', { src: src }).appendTo('body');
  
  window[callback] = function(){ loader.resolve() };
}))
.done(function(){
  // something like this
  var defaultLocation = new google.maps.LatLng(33.990,-118.459);
  /* etc */
});

No comments: