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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5334977/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 16:44:12  来源:igfitidea点击:

Is there a way to detect if the Facebook Javascript SDK loaded successfully?

javascriptfacebooksdk

提问by Chaddeus

I use Facebook as the membership system of my website. It uses the code to generate a login control, allowing users to login via their facebook account. It's essentially one click if they're already a member, 2 if they're not (for granting permissions).

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

I got a problem though... feedback is suggesting the login button isn't always loading correctly. Instead of loading the facebook login control, it simply states (in text) "login via facebook" - which is what the login button would say if the control loaded successfully.

我遇到了一个问题...反馈表明登录按钮并不总是正确加载。它没有加载 facebook 登录控件,而是简单地(以文本形式)声明“通过 facebook 登录”——如果控件加载成功,登录按钮会说这句话。

Testing shows that is what happens when the facebook javascript SDK fails to load completely (for whatever reason). I've seen instances where a # in the url prevents the SDK from loading.

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

To better support this issue, how would I go about detecting if the facebook javascript SDK loaded, and is ready? That way, if it fails, I can leave some sort of note for the user.

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

Here's how it's currently added to the page:

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

<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>

回答by ifaour

You should load the Javascript Library Asynchronouslyand put all your FB related functions inside the window.fbAsyncInitmethod:

您应该异步加载Javascript 库并将所有与 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>

This code loads the SDK asynchronously so it does not block loading other elements of your page. This is particularly important to ensure fast page loads for users and SEO robots.

The URLs in the above code are protocol relative. This lets the browser to load the SDK over the same protocol (HTTP or HTTPS) as the containing page, which will prevent "Insecure Content" warnings.

The function assigned to window.fbAsyncInitis run as soon as the SDK is loaded. Any code that you want to run after the SDK is loaded should be placed within this function and after the call to FB.init. For example, this is where you would test the logged in statusof the user or subscribe to any Facebook eventsin which your application is interested.

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

上面代码中的 URL 是与协议相关的。这允许浏览器通过与包含页面相同的协议(HTTP 或 HTTPS)加载 SDK,这将防止“不安全内容”警告。

分配给的函数会window.fbAsyncInit在 SDK 加载后立即运行。您希望在 SDK 加载后运行的任何代码都应放置在此函数中并在调用FB.init. 例如,您可以在此处测试用户的登录状态订阅您的应用程序感兴趣的任何 Facebook 事件

A quick example is the following:

一个简单的例子如下:

<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
(Just clicked the checklink a couple of times)

在此处输入图片说明
只是点击了check几次链接



Please note that you can still construct the Login Link server-side and WITHOUTJavaScript. Example using the PHP-SDK:

请注意,您仍然可以在没有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>

回答by Leo Romanovsky

Trigger an event when the SDK is loaded:

SDK加载时触发事件:

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

And listen for the event like this:

并像这样监听事件:

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

回答by Mohammad Arif

Just look for FB object after loading FB JS SDK sync/async as given:

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

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

That's a enough check to call any Facebook JS API related method safely.

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

回答by Simon_Weaver

If you are using jQuery (and you have loaded jQuery prior to the FB initialization) you can use a Deferred to run additional initialization.

如果您正在使用 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>

Then elsewhere (in a JS file) you can do this (in fact the key of this method is you can put this in as many places as you want and they will all get triggered):

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

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

Note: If the initialization completes BEFORE you add the doneevent it will fire immediately (that is how Deferreds work). So you can put it wherever you want.

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

Be sure to test what you want the behavior to be if the API is never initializaed (just comment out the (function(d,s,id)... part

如果 API 从未初始化,请务必测试您想要的行为(只需注释掉 (function(d,s,id)... part

回答by Brad

Promise-based version, for modern browsers

基于 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 ...
});

回答by Alex Mcp

What globals does this JS file introduce?

这个JS文件引入了哪些全局变量?

Let's say it creates a

假设它创建了一个

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

You can test for if (FaceBook)and go from there.

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

It seems likely that they give you some sort of load event for when their framework is booted up, so to speak.

可以这么说,当他们的框架启动时,他们似乎可能会为您提供某种加载事件。

回答by Atul

According to this page http://www.techsirius.com/2014/04/detect-social-SDK-didnt-load.html

根据这个页面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');
   }
});

回答by Monkey Monk

I use this from few days :

我从几天开始使用它:

var isLoaded = false;

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

        // ...
    }
});

What do you think ?

你怎么认为 ?

回答by Ithar

As stated in other answers; with thanks to @ifaour & @Leo Romanovsky; the best way to detect if the SDK is loaded successully is to trigger an event when the fbAsyncInit is called.

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

If the event is captured then the SDK is loaded. The code below shows how this could be achieved:

如果事件被捕获,则 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.");
    });
});

In the event that the event is not fired you could add a timer to check if FB object is 'undefined' and show the appropriate message.

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

Note 1:Downside there could a slight delay till this event is fired.

注意 1:在触发此事件之前可能会有轻微的延迟。

Note 2:"feedback is suggesting the login button isn't always loading correctly". I know that FFv49 private browsing blocks the call to fb.

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

回答by Barno

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]);
        }
    });
}

If you want check the status from another javascript (with the suggestion of @Leo Romanovsky )

如果您想从另一个 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")
        }

    });