有没有办法检测Facebook Javascript SDK是否成功加载?

时间:2011-03-17 04:49:38

标签: javascript facebook sdk

我使用Facebook作为我网站的会员制。它使用代码生成登录控件,允许用户通过他们的Facebook帐户登录。如果他们已经是会员,那基本上就是一次点击;如果他们不是,那就是2次点击(用于授予权限)。

我遇到了问题...反馈表明登录按钮并不总是正确加载。它不是加载facebook登录控件,而是简单地说明(在文本中)“通过facebook登录” - 如果控件成功加载,这就是登录按钮会说的。

测试表明,当facebook javascript SDK无法完全加载(无论出于何种原因)时会发生这种情况。我见过url中的#阻止SDK加载的实例。

为了更好地支持这个问题,我将如何检测facebook javascript SDK是否已加载并准备好了?这样,如果它失败了,我可以为用户留下某种注意事项。

以下是它当前添加到页面的方式:

<script>
window.fbAsyncInit = function () {
FB.init({
  appId: '***************',
  status: true,
  cookie: true,
  xfbml: true
});
FB.Event.subscribe('auth.login', function (response) {
  window.location.reload();
});

};
(function () {
  var e = document.createElement('script'); e.async = true;
  e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
  document.getElementById('fb-root').appendChild(e);
} ());

</script>

11 个答案:

答案 0 :(得分:47)

您应该加载Javascript Library Asynchronously并将所有与FB相关的函数放在window.fbAsyncInit方法中:

<div id="fb-root"></div>
<script>
  window.fbAsyncInit = function() {
    FB.init({
      appId      : 'YOUR_APP_ID', // App ID
      channelUrl : '//WWW.YOUR_DOMAIN.COM/channel.html', // Channel File
      status     : true, // check login status
      cookie     : true, // enable cookies to allow the server to access the session
      xfbml      : true  // parse XFBML
    });

    // Additional initialization code here
  };

  // Load the SDK Asynchronously
  (function(d){
     var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
     if (d.getElementById(id)) {return;}
     js = d.createElement('script'); js.id = id; js.async = true;
     js.src = "//connect.facebook.net/en_US/all.js";
     ref.parentNode.insertBefore(js, ref);
   }(document));
</script>
  

此代码异步加载SDK,因此不会阻止加载   您网页的其他元素。这对于确保尤为重要   为用户和SEO机器人加载快速页面。

     

上述代码中的URL是协议相对的。这让我们   浏览器通过与之相同的协议(HTTP或HTTPS)加载SDK   包含页面,这将阻止“不安全内容”警告。

     

分配给window.fbAsyncInit的功能在SDK完成后立即运行   已加载。加载SDK后要运行的任何代码   应该放在这个函数中,并在调用FB.init之后。   例如,this is where you would test the logged in status   用户或您的应用程序所在的subscribe to any Facebook events   感兴趣。

以下是一个简单的例子:

<div id="fb-root"></div>
<script>
  var isLoaded = false;
  window.fbAsyncInit = function() {
    FB.init({
      appId      : 'YOUR_APP_ID', // App ID
      channelUrl : '//WWW.YOUR_DOMAIN.COM/channel.html', // Channel File
      status     : true, // check login status
      cookie     : true, // enable cookies to allow the server to access the session
      xfbml      : true  // parse XFBML
    });
    isLoaded = true;

    // Additional initialization code here
  };

  function checkIfLoaded() {
    if(isLoaded) console.log("LOADED!");
    else console.log("NOT YET!");

    return false;
  }

  // Load the SDK Asynchronously
  (function(d){
     var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
     if (d.getElementById(id)) {return;}
     js = d.createElement('script'); js.id = id; js.async = true;
     js.src = "//connect.facebook.net/en_US/all.js";
     ref.parentNode.insertBefore(js, ref);
   }(document));
</script>
<a href="#" onclick="checkIfLoaded();">Check</a>

enter image description here
只需点击check链接几次


请注意,您仍然可以构建Login Link服务器端和 WITHOUT JavaScript。使用PHP-SDK的示例:

$loginUrl = $facebook->getLoginUrl();
...
...
<a href="<?php echo $loginUrl; ?>">
    <img src="http://static.ak.fbcdn.net/rsrc.php/zB6N8/hash/4li2k73z.gif">
</a>

答案 1 :(得分:8)

加载SDK时触发事件:

window.fbAsyncInit = function() {
  FB.init({appId: "#{KeyManager.facebook_app_id}", status: true, cookie: true, xfbml: true});
  jQuery('#fb-root').trigger('facebook:init');
};

听听这样的事件:

$("#fb-root").bind("facebook:init", function() {
  ..
});

答案 2 :(得分:4)

在加载FB JS SDK同步/异步后,只需查看FB对象:

            if (typeof FB !== 'undefined') {
                alert("FB JS API is available now");
            } else {alert("do something...")}

这是一个足够的检查,可以安全地调用任何与Facebook JS API相关的方法。

答案 3 :(得分:3)

这个JS文件引入了什么全局变量?

假设它创建了一个

var FaceBook = function() {//make friends! Or whatever...}

您可以测试if (FaceBook)并从那里开始。

很可能他们会在启动框架时为你提供某种加载事件,可以这么说。

答案 4 :(得分:3)

根据此页面http://www.techsirius.com/2014/04/detect-social-SDK-didnt-load.html

$(window).load(function(){
   if(typeof window.FB == 'undefined'){
       alert('Facebook SDK is unable to load, display some alternative content for visitor');
   }
   else{
      alert('Facebook is working just fine');
   }
});

答案 5 :(得分:2)

如果您正在使用jQuery(并且在FB初始化之前已经加载了jQuery),则可以使用Deferred来运行其他初始化。

<script>
    window.fbLoaded = $.Deferred();

    window.fbAsyncInit = function() {

        FB.init({
            appId      : '----------',
            xfbml      : true,
            status     : true,
            version    : 'v2.7'
        });

        window.fbLoaded.resolve();
    };


    (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'));

</script>

然后在其他地方(在JS文件中)你可以这样做(实际上这个方法的关键是你可以把它放在你想要的任意数量的地方,它们都会被触发):

 window.fbLoaded.done(function () { alert('FB initialized'); });

注意:如果初始化完成,则在添加done事件之前,它将立即触发(这是Deferreds的工作方式)。所以你可以把它放在任何你想要的地方。

如果API从未初始化,请务必测试您希望行为是什么(只需注释掉(function(d,s,id)... part

答案 6 :(得分:2)

基于Promise的版本,适用于现代浏览器

// Load Facebook JS SDK
(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 = 'https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v2.11';
  fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));

// Create a new promise, set to resolve using the global function `fbAsyncInit`,
// which the Facebook JS SDK will call once it's ready.
(new Promise((resolve, reject) => {
  window.fbAsyncInit = resolve;
}).then(() => {
  // ... your code here ...
});

答案 7 :(得分:0)

动态加载脚本(从js添加脚本标记)并检查错误/成功事件。

答案 8 :(得分:0)

var FB;
jQuery.fbInit = function(app_id) {
    window.fbAsyncInit = function() {
        FB.init({
            appId      : app_id, 
            status     : true, 
            channelUrl: '#', 
            cookie     : true, 
            xfbml      : true  
        });
        FB = FB;
        getLoginStatus();
    };
    // Load the SDK Asynchronously
    (function(d){
        var js, id = 'facebook-jssdk'; if (d.getElementById(id)) {return;}
        js = d.createElement('script'); js.id = id; js.async = true;
        js.src = "//connect.facebook.net/it_IT/all.js";
        d.getElementsByTagName('head')[0].appendChild(js);
    }(document));

    $('<div />').attr('id','fb-root').appendTo('body');
};

/**
 * https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus/
 */
function getLoginStatus() {
    FB.getLoginStatus(function(response) {
        if (response.status === 'connected') {
            $('#fb-root').trigger('facebook:init',[response]);
        } else if (response.status === 'not_authorized') {
            $('#fb-root').trigger('facebook:init',[response]);
        } else {
            $('#fb-root').trigger('facebook:init',[response]);
        }
    });
}

如果你想从另一个javascript检查状态(建议@Leo Romanovsky)

 $("#fb-root").on("facebook:init", function(event, response) {
        if(response.status === 'connected') {
            alert("logged with FB")
        }else{
            alert("No Logged with FB")
        }

    });

答案 9 :(得分:0)

我几天就用这个:

var isLoaded = false;

$(document).on('DOMSubtreeModified', function () {
    if ($('#fb-root').length && !isLoaded) {
        isLoaded = true;

        // ...
    }
});

您怎么看?

答案 10 :(得分:0)

如其他答案所述;感谢@ifaour&amp; @Leo Romanovsky;检测SDK是否已成功加载的最佳方法是在调用fbAsyncInit时触发事件。

如果捕获事件,则加载SDK。下面的代码显示了如何实现这一目标:

<div id="fb-root"></div>
<script>
  window.fbAsyncInit = function() {
    FB.init({
      appId      : 'YOUR_APP_ID', // App ID
      status     : true, // check login status
      cookie     : true, // enable cookies to allow the server to access the session
      xfbml      : true  // parse XFBML
    });

    // Fire an event when the FB library asynchronously is loaded
    $("#fb-root").trigger("facebook:init");

    // Additional initialization code here
  };

  // 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"));
</script>

// Somewhere else in the code
$(document).ready(function () {
    $("#fb-root").bind("facebook:init", function () {
        console.log("The event is fired FB SDK object is ready to be used.");
    });
});

如果事件未被触发,您可以添加一个计时器来检查FB对象是否为“未定义”并显示相应的消息。

注1:在此事件被解雇之前可能会有一点延迟。

注2:“反馈表明登录按钮并不总是正确加载”。我知道FFv49私密浏览阻止了对fb的调用。