旧的JS SDK有一个名为FB.ensureInit的函数。新SDK似乎没有这样的功能......我怎样才能确保在完全启动之前不进行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>
答案 0 :(得分:138)
2012年1月4日更新
似乎你不能像以前一样在FB.getAuthResponse()
之后调用依赖于FB的方法(例如FB.init()
),因为FB.init()
现在似乎是异步的。将代码包装到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
内放一些回调函数:
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
};
如果你想要完全替换FB.ensureInit那么你必须自己写一些东西,因为没有官方替代品(大错误imo)。这是我使用的:
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");
});
答案 1 :(得分:35)
实际上,Facebook已经提供了一种订阅身份验证事件的机制。
在您的情况下,您使用的是“ status:true ”,这意味着FB对象将请求Facebook获取用户的登录状态。
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 事件 BEFORE 您调用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之后立即运行任何代码,因为不会有异步调用。
答案 2 :(得分:12)
如果您使用jquery和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
};
答案 3 :(得分:9)
另一种检查FB是否已初始化的方法是使用以下代码:
ns.FBInitialized = function () {
return typeof (FB) != 'undefined' && window.fbAsyncInit.hasRun;
};
因此,在您的页面就绪事件中,您可以检查ns.FBInitialized并使用setTimeOut将事件推迟到以后阶段。
答案 4 :(得分:5)
虽然上面的一些解决方案有效,但我想我会发布我们的最终解决方案 - 它定义了一个'就绪'方法,一旦FB初始化并准备好就会触发。它具有优于其他解决方案的优势,可以在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
};
})();
答案 5 :(得分:4)
编辑注意:我已经更新了以下帮助程序脚本并创建了一个更容易/更简单的类;在这里查看::: https://github.com/tjmehta/fbExec.js
window.fbAsyncInit = function() {
FB.init({
//...
});
window.fbApiInit = true; //init flag
if(window.thisFunctionIsCalledAfterFbInit)
window.thisFunctionIsCalledAfterFbInit();
};
fbEnsureInit将在FB.init
之后调用它的回调function fbEnsureInit(callback){
if(!window.fbApiInit) {
window.thisFunctionIsCalledAfterFbInit = callback; //find this in index.html
}
else{
callback();
}
}
fbEnsureInitAndLoginStatus将在FB.init之后和FB.getLoginStatus之后调用它的回调
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.
}
});
});
}
(FB.login需要在FB初始化后运行)
fbEnsureInit(function(){
FB.login(
//..enter code here
);
});
(FB.api需要在FB.init之后运行,FB用户必须登录。)
fbEnsureInitAndLoginStatus(function(){
FB.api(
//..enter code here
);
});
答案 6 :(得分:4)
我不会使用任何setTimeout或setInterval,而是坚持使用延迟对象(jQuery here实现)。在适当的时刻解决队列仍然很棘手,因为init没有回调但是将结果与事件订阅相结合(正如有人在我之前指出的那样),应该做的伎俩并且足够接近。
Pseudo-snippet看起来如下:
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();
});
答案 7 :(得分:4)
这是一种更简单的方法,既不需要事件也不需要超时。但它确实需要jQuery。
使用jQuery.holdReady()
(docs)
因此,在您的jQuery脚本之后,立即延迟就绪事件。
<!-- 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初始化功能中,发布它:
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 );
答案 8 :(得分:2)
您可以订阅该活动:
IE)
FB.Event.subscribe('auth.login', function(response) {
FB.api('/me', function(response) {
alert(response.name);
});
});
答案 9 :(得分:2)
小但重要的通知:
FB.getLoginStatus
必须在FB.init
之后调用,否则不会触发事件。
您可以使用FB.Event.subscribe('auth.statusChange', callback)
,但在用户未登录Facebook时不会触发。
这是两个函数的工作示例
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'));
答案 10 :(得分:1)
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,在我看来这似乎有助于登录用户界面并更可靠地推动功能。
答案 11 :(得分:1)
有时fbAsyncInit不起作用。我不知道为什么然后使用这个解决方法:
DECLARE
FUNCTION f
RETURN DATE IS
BEGIN
RETURN NULL;
END f;
BEGIN
DBMS_OUTPUT.put_line (NVL (TRUNC (f), TRUNC (SYSDATE)));
END;