如何检测Facebook的FB.init何时完成
旧的JS SDK有一个叫做FB.ensureInit的函数。 新的SDK似乎没有这样的function…我怎么才能确保我不会使API调用,直到它完全启动?
我把它包含在每一页的顶部:
<div id="fb-root"></div> <script> 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(); }; (function() { var e = document.createElement('script'); e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js'; e.async = true; document.getElementById('fb-root').appendChild(e); }()); </script>
2012年1月4日更新
看起来像FB.init()
类的FB.init()
之后, FB.init()
似乎不能立即调用FB相关的方法(例如FB.getAuthResponse()
),因为FB.init()
似乎是asynchronous的。 将代码包装到FB.getLoginStatus()
响应中,似乎可以检测API何时完全准备就绪:
window.fbAsyncInit = function() { FB.init({ //... }); FB.getLoginStatus(function(response){ runFbInitCriticalCode(); }); };
或者如果从下面使用fbEnsureInit()
实现:
window.fbAsyncInit = function() { FB.init({ //... }); FB.getLoginStatus(function(response){ fbApiInit = true; }); };
原帖:
如果你想在FB初始化的时候运行一些脚本,你可以在fbAsyncInit
一些callback函数:
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 };
如果你想精确的replaceFB.ensureInit,那么你将不得不自己写一些东西,因为没有正式的replace(大错误)。 这是我使用的:
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(); } } }
用法:
fbEnsureInit(function() { console.log("this will be run once FB is initialized"); });
实际上Facebook已经提供了订阅authentication事件的机制。
在你的情况下,你正在使用“ 状态:真 ”,这意味着FB对象将要求Facebook的用户的login状态。
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.getLoginStatus()”您再次运行相同的请求。
相反,您可以使用FB.Event.subscribe订阅auth.statusChange或auth.authResponseChange事件, 然后再调用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 });
最有可能的是,当使用“ status:false ”时,你可以在FB.init之后运行任何代码,因为不会有asynchronous调用。
这里是一个解决scheme,以防你使用jQuery和Facebookasynchronous延迟加载:
// 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 };
检查FB是否已初始化的另一种方法是使用以下代码:
ns.FBInitialized = function () { return typeof (FB) != 'undefined' && window.fbAsyncInit.hasRun; };
因此,在您的页面就绪事件中,您可以检查ns.FBInitialized,并使用setTimeOut将事件推迟到以后的阶段。
虽然上面的一些解决scheme的工作,我想我会发布我们最终的解决scheme – 它定义了一个“准备好”的方法,只要FB初始化并准备就绪,将触发。 它比其他解决scheme具有优势,在FB准备就绪之前或之后调用是安全的。
它可以像这样使用:
f52.fb.ready(function() { // safe to use FB here });
这里是源文件(注意它是在'f52.fb'命名空间中定义的)。
if (typeof(f52) === 'undefined') { f52 = {}; } f52.fb = (function () { var fbAppId = f52.inputs.base.fbAppId, fbApiInit = false; var awaitingReady = []; var notifyQ = function() { var i = 0, l = awaitingReady.length; for(i = 0; i < l; i++) { awaitingReady[i](); } }; var ready = function(cb) { if (fbApiInit) { cb(); } else { awaitingReady.push(cb); } }; window.fbAsyncInit = function() { FB.init({ appId: fbAppId, xfbml: true, version: 'v2.0' }); FB.getLoginStatus(function(response){ fbApiInit = true; notifyQ(); }); }; return { /** * Fires callback when FB is initialized and ready for api calls. */ 'ready': ready }; })();
我已经通过使用全局函数避免使用setTimeout:
编辑注:我已经更新了以下帮助脚本,并创build了一个更容易/更简单的类; 看看这里::: https://github.com/tjmehta/fbExec.js
window.fbAsyncInit = function() { FB.init({ //... }); window.fbApiInit = true; //init flag if(window.thisFunctionIsCalledAfterFbInit) window.thisFunctionIsCalledAfterFbInit(); };
fbEnsureInit会在FB.init之后调用它的callback函数
function fbEnsureInit(callback){ if(!window.fbApiInit) { window.thisFunctionIsCalledAfterFbInit = callback; //find this in index.html } else{ callback(); } }
fbEnsureInitAndLoginStatus将在FB.init和FB.getLoginStatus之后调用它的callback函数
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示例用法:
(在FB初始化后需要运行FB.login)
fbEnsureInit(function(){ FB.login( //..enter code here ); });
fbEnsureInitAndLogin示例用法:
(在FB.init和FB用户必须login后需要运行FB.api。)
fbEnsureInitAndLoginStatus(function(){ FB.api( //..enter code here ); });
而不是使用任何setTimeout或setInterval我会坚持推迟的对象(由jQuery 在这里实现)。 在适当的时候解决队列还是很棘手的,因为init没有callback,但是把结果和事件订阅结合起来(正如有人指出的那样),应该做到这一点,并且足够接近。
伪代码将如下所示:
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(); });
这是一个更简单的方法,既不需要事件,也不需要超时。 但是,它确实需要jQuery。
使用jQuery.holdReady()
(docs)
所以,紧跟在你的jQuery脚本之后,延迟ready事件。
<!-- 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>
然后,在你的Facebook init函数中,释放它:
window.fbAsyncInit = function() { FB.init({ appId: '11111111111111', cookie: true, xfbml: false, version: 'v2.4' }); // release the ready event to execute $.holdReady( false ); };
然后,您可以正常使用ready事件:
$(document).ready( myApp.init );
Facebook API监视FB._apiKey,因此您可以在调用您自己的API应用程序之前观察此情况,如下所示:
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(); };
不知道这是否有所作为,但在我的情况 – 因为我想确保用户界面已经准备好了 – 我用jQuery的文档准备好了(最后一位在上面):
$(document).ready(FBreadyState);
还要注意,我没有使用async = true加载Facebook的all.js,在我的情况下似乎是帮助login到用户界面和更可靠地驱动function。
您可以订阅该事件:
即)
FB.Event.subscribe('auth.login', function(response) { FB.api('/me', function(response) { alert(response.name); }); });
有时fbAsyncInit不起作用。 我不知道为什么,然后使用此解决方法:
var interval = window.setInterval(function(){ if(typeof FB != 'undefined'){ FB.init({ appId : 'your ID', cookie : true, // enable cookies to allow the server to access// the session xfbml : true, // parse social plugins on this page version : 'v2.3' // use version 2.3 }); FB.getLoginStatus(function(response) { statusChangeCallback(response); }); clearInterval(interval); } },100);
小但重要通知:
-
必须在
FB.init
之后调用FB.init
,否则不会触发事件。 -
你可以使用
FB.Event.subscribe('auth.statusChange', callback)
,但是当用户没有在facebook上login时不会触发。
这是两个函数的工作示例
window.fbAsyncInit = function() { FB.Event.subscribe('auth.statusChange', function(response) { console.log( "FB.Event.subscribe auth.statusChange" ); console.log( response ); }); FB.init({ appId : "YOUR APP KEY HERE", cookie : true, // enable cookies to allow the server to access // the session xfbml : true, // parse social plugins on this page version : 'v2.1', // use version 2.1 status : true }); FB.getLoginStatus(function(response){ console.log( "FB.getLoginStatus" ); console.log( response ); }); }; // 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'));
- Python – Facebook的API – 需要一个工作的例子
- 为什么Facebook的PHP SDK getUser总是返回0?
- Facebook API – 如何通过Facebook API获取Facebook用户的个人资料图片(无需用户“允许”该应用程序)
- Facebook Graph API – 使用JavaScript上传照片
- 在Chrome中,Facebook给出了“不安全的JavaScript尝试访问带有URL的框架”错误
- Chrome webkit inspector中不断产生“不安全的JavaScript尝试访问带有URL的帧…”错误
- Android的Facebook集成无效的密钥哈希
- 检查扩展权限与新的Facebook的JavaScript的SDK
- Facebook:不安全的JavaScript问题(document.domain值应该是相同的)