I would like to load FB SDK using require.js.
my test case is something like this:
test.js:
require([
'libs/facebook/fb'
], function(FB){
FB.api("/me", function(){});
));
I would like to have test.js run only after FB SDK is loaded, and have FB ready for it.
Any thoughts on how this can be achieved? what should my wrapper (libs/facebook/fb.js) have?
I would like to load FB SDK using require.js.
my test case is something like this:
test.js:
require([
'libs/facebook/fb'
], function(FB){
FB.api("/me", function(){});
));
I would like to have test.js run only after FB SDK is loaded, and have FB ready for it.
Any thoughts on how this can be achieved? what should my wrapper (libs/facebook/fb.js) have?
Share Improve this question asked Aug 7, 2012 at 13:12 Erez RosovskyErez Rosovsky 6337 silver badges11 bronze badges 1- 1 Looks like Facebook has finally addressed this, their solution looks quite similar to some of the answers on this question. developers.facebook.com/docs/howto/javascript/requirejs – Randy L Commented May 28, 2013 at 16:59
4 Answers
Reset to default 10 +50It doesn't seem like the FB API is an AMD module, so it doesn't define itself in a manner to which RequireJS is accustomed to. You will need to shim the FB API using require.config. I'm assuming test.js is the script you have provided as the data-main value for RequireJS.
require.config({
shim: {
'facebook' : {
exports: 'FB'
}
},
paths: {
'facebook' : 'libs/facebook/fb'
}
});
require(['facebook'], function(FB){
FB.api('/me', function(){});
});
Or wrap the init code in a module (the sample uses Dojo):
define( 'facebook',
[ 'dojo/dom-construct',
'dojo/_base/window',
'https://connect.facebook.net/en_US/all/debug.js' ], // remove "/debug" in live env
function( domConstruct, win )
{
// add Facebook div
domConstruct.create( 'div', { id:'fb-root' }, win.body(), 'first' );
// init the Facebook JS SDK
FB.init( {
appId: '1234567890', // App ID from the App Dashboard
channelUrl: '//' + window.location.hostname + '/facebook-channel.html', // Channel File for x-domain communication
status: true, // check the login status upon init?
cookie: true, // set sessions cookies to allow your server to access the session?
xfbml: true // parse XFBML tags on this page?
} );
// Additional initialization code such as adding Event Listeners goes here
console.log( 'Facebook ready' );
return FB;
}
);
Here is a Documentation from Facebook: https://developers.facebook.com/docs/javascript/howto/requirejs/
require.config({
shim: {
'facebook' : {
export: 'FB'
}
},
paths: {
'facebook': '//connect.facebook.net/en_US/all'
}
})
require(['fb']);
and then add the module like this:
define(['facebook'], function(){
FB.init({
appId : 'YOUR_APP_ID',
channelUrl : '//yourdomain.com/channel.html'
});
FB.getLoginStatus(function(response) {
console.log(response);
});
});
Building on voidstate's and Dzulqarnain Nasir's Answers, here is the code I ended up using on my project.
The part that tripped me up the most was that FB.init()
is apparently asynchronous. In trying to envoke the callback()
(without FB.getLoginStatus
), FB
was not yet initialized, and I was getting "An active access token must be used to query information about the current user.
" errors.
RequireJS Shim Config
require.config({
// paths: { 'facebookSDK': '//connect.facebook.net/en_US/all/debug' }, // development
paths: { 'facebookSDK': '//connect.facebook.net/en_US/all' }, // production
shim: { 'facebookSDK': { exports: 'FB' } }
});
AMD Module to Initialize Facebook JS SDK
define(['facebookSDK'], function (FB) {
'use strict';
return function (settings, callback) {
var args = {
appId: settings.appId,
channelUrl: settings.channelUrl,
status: true,
cookie: true,
xfbml: true
};
console.log('Calling FB.init:', args);
FB.init(args);
if (callback && typeof (callback) === "function") {
// callback() // does not work, FB.init() is not yet finished
FB.getLoginStatus(callback);
}
};
});
This still doesn't quite address the Original Question's desired usage.
OP's code could maybe be rewritten as:
require(['libs/facebook/fb'], // where fb.js holds my above Module
function(FBinit){
FBinit({
appId: appId,
channelUrl: channelUrl
}, function(){
FB.api("/me", function(){});
});
}
);
This isn't quite as cleanas OP's original concept, but its the best I could figure out. If anyone has any, I'd love some feedback or advice on how to improve my approach. I am still very much new to RequireJS.