web-dev-qa-db-fra.com

Existe-t-il un moyen de détecter si le SDK Javascript de Facebook a été chargé avec succès?

J'utilise Facebook comme système d'adhésion de mon site Web. Il utilise le code pour générer un contrôle de connexion, permettant aux utilisateurs de se connecter via leur compte Facebook. C'est essentiellement un clic s'ils sont déjà membres, 2 s'ils ne le sont pas (pour accorder des autorisations).

J'ai un problème cependant ... les commentaires suggèrent que le bouton de connexion ne se charge pas toujours correctement. Au lieu de charger le contrôle de connexion facebook, il indique simplement (dans le texte) "connexion via facebook" - ce que dirait le bouton de connexion si le contrôle était chargé avec succès.

Les tests montrent que c'est ce qui se produit lorsque le SDK de javascript de Facebook ne parvient pas à se charger complètement (pour une raison quelconque). J'ai vu des cas où un # dans l'URL empêche le SDK de se charger.

Pour mieux prendre en charge ce problème, comment pourrais-je détecter si le SDK de javascript de Facebook est chargé et s'il est prêt? De cette façon, si cela échoue, je peux laisser une sorte de note à l'utilisateur.

Voici comment il est actuellement ajouté à la 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>
30
Chaddeus

Vous devez charger la bibliothèque Javascript de manière asynchrone et placer toutes vos fonctions liées au bloc fonction dans la méthode 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>

Ce code charge le SDK de manière asynchrone afin qu'il ne bloque pas le chargement d'autres éléments de votre page. Ceci est particulièrement important pour assurer chargement rapide de pages pour les utilisateurs et les robots de référencement.

Les URL dans le code ci-dessus sont relatives au protocole. Cela laisse le navigateur pour charger le SDK sur le même protocole (HTTP ou HTTPS) que le fichier contenant la page, ce qui empêchera les avertissements de "contenu non sécurisé".

La fonction assignée à window.fbAsyncInit est exécutée dès que le SDK est chargé. Tout code que vous souhaitez exécuter après le chargement du SDK devrait être placé dans cette fonction et après l'appel à FB.init. Par exemple, c’est là que vous testez l’état de connexion du fichier utilisateur ou vous abonner à n’importe quel événement Facebook dans lequel votre application est intéressé.

Un exemple rapide est le suivant: 

<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
(Il suffit de cliquer deux fois sur le lien check} _)


Veuillez noter que vous pouvez toujours construire le lien de connexion côté serveur et _ sans JavaScript. Exemple utilisant le PHP-SDK

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

Déclencher un événement lorsque le SDK est chargé:

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

Et écoutez l'événement comme ceci:

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

Il suffit de rechercher un objet FB après le chargement du FB JS SDK sync/async comme indiqué:

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

C'est une vérification suffisante pour appeler n'importe quelle méthode liée à l'API JS de Facebook en toute sécurité.

4
Mohammad Arif

Selon cette page 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');
   }
});
3
Atul

Quels globaux ce fichier JS introduit-il?

Disons que cela crée un 

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

Vous pouvez tester if (FaceBook) et partir de là.

Il semble probable qu'ils vous donnent une sorte d'événement de chargement lorsque leur infrastructure est démarrée, pour ainsi dire.

3
Alex Mcp

Si vous utilisez jQuery (et que vous avez chargé jQuery avant l'initialisation du FB), vous pouvez utiliser une opération différée pour exécuter une initialisation supplémentaire.

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

Ensuite, ailleurs (dans un fichier JS), vous pouvez le faire (en fait, la clé de cette méthode est de pouvoir le placer à autant d’endroits que vous le souhaitez et ils seront tous déclenchés):

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

Remarque: Si l'initialisation est terminée AVANT que vous ajoutiez l'événement done, il se déclenchera immédiatement (c'est ainsi que fonctionne la procédure différée). Vous pouvez donc le placer où vous voulez. 

Assurez-vous de tester le comportement souhaité si l’API n’est jamais initialisée (il suffit de commenter le (function(d,s,id)... part

2
Simon_Weaver

Version basée sur Promise, pour les navigateurs modernes

// 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 ...
});
2
Brad

Je l'utilise depuis quelques jours:

var isLoaded = false;

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

        // ...
    }
});

Qu'est-ce que tu penses ?

0
Monkey Monk

Comme indiqué dans d'autres réponses; avec merci à @ifaour & @Leo Romanovsky; Le meilleur moyen de détecter si le SDK est chargé est de déclencher un événement lorsque fbAsyncInit est appelé. 

Si l'événement est capturé, le SDK est chargé. Le code ci-dessous montre comment cela pourrait être réalisé:

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

Si l'événement n'est pas déclenché, vous pouvez ajouter une minuterie pour vérifier si l'objet FB est «non défini» et afficher le message approprié.

Note 1: Inconvénient: il pourrait y avoir un léger retard jusqu'à ce que cet événement soit déclenché.

Note 2: "les commentaires suggèrent que le bouton de connexion ne se charge pas toujours correctement". Je sais que la navigation privée FFv49 bloque l'appel à fb.

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

Si vous voulez vérifier le statut d'un autre javascript (avec la suggestion de @Leo Romanovsky)

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

    });
0
Barno

Chargez le script de manière dynamique (ajoutez une balise de script à partir de js) et recherchez les événements d'erreur/de succès.

0
Tom