如何检测 facebook 的 FB.init 何时完成

IT技术 javascript facebook
2021-02-26 23:02:50

旧的 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>
6个回答

2012 年 1 月 4 日更新

似乎您不能像以前一样立即调用依赖于 FB 的方法(例如FB.getAuthResponse()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");
});
@beanland,fql.query api 调用要求用户已登录。您确定在从response返回后正在运行查询FB.getLoginStatus(function(response){}吗?- 请注意上面“更新的答案”与“原始答案”的区别。
2021-04-25 23:02:50
@serg 谢谢你的例子。我不得不延迟我的内部函数fbAsyncInit,以便在加载后调用它window.fbAsyncInit = function() { FB.init({ appId : '*************', channelUrl : 'http://www.mydomain.com', status : true, // check login status cookie : true, // enable cookies to allow the server to access the session oauth : true, // enable OAuth 2.0 xfbml : true // parse XFBML }); setTimeout(function() { myfunction(function (callback) {}, '', '', '' ); }, 1200); };
2021-04-29 23:02:50
谢谢塞尔格..你是个传奇!
2021-05-07 23:02:50
感谢您的更新 - 我遇到了同样的问题,您更新后的解决方案运行良好!
2021-05-07 23:02:50
我无法在调用 FB.init 后立即运行 Facebook API 请求——也许是因为我使用的方法是“fql.query”?无论哪种方式,我都必须在 fbApiInit 标志上设置长时间的超时。
2021-05-13 23:02:50

实际上 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.init之前使用FB.Event.subscribe订阅auth.statusChangeauth.authResponseChange事件

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 之后立即运行任何代码,因为不会有异步调用。

注意:使用此方法唯一需要注意的是,如果您未登录,则不会触发该事件。只需将您的默认 UI 状态设置为未经过身份验证,即可完美运行。然后,您可以在事件处理程序中检查 connected 或 not_authorized。
2021-04-24 23:02:50
此外,对于前端应用程序,要在刷新之间保持用户登录状态,cookietrue在 init param 对象中设置
2021-05-02 23:02:50

这是您使用的解决方案 和 Facebook 异步延迟加载:

// 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
};
我喜欢它!唯一的问题是 Facebook 坚持你应该在开始的 <body> 标签之后直接包含你的 FB init 代码,而最佳实践是你应该在结束的 <body> 标签之前加载 jQuery。呸!鸡肉和鸡蛋。我很想说“去你的,Facebook”并在 jQuery 之后加载 FB。
2021-04-17 23:02:50
version: 'v2.5'在 init json 中添加,否则它将无法工作..至少不适合我。谢谢您的帮助
2021-04-18 23:02:50
@EthanBrown 我同意 - 您的页面可能比 FB 更需要 jQuery,所以这是有道理的。几年前,我放弃了在页面末尾加载 jQuery 的尝试;-)
2021-04-23 23:02:50

检查 FB 是否已初始化的另一种方法是使用以下代码:

ns.FBInitialized = function () {
    return typeof (FB) != 'undefined' && window.fbAsyncInit.hasRun;
};

因此,在您的页面就绪事件中,您可以检查 ns.FBInitialized 并使用 setTimeOut 将事件推迟到稍后阶段。

这是一个简单的。喜欢它
2021-04-17 23:02:50
这才是真实的!谢谢!
2021-04-20 23:02:50

虽然上述一些解决方案有效,但我想我会发布我们的最终解决方案 - 它定义了一个“就绪”方法,该方法将在 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
    };

})();