web-dev-qa-db-fra.com

Comment détecter quand le FB.init de Facebook est terminé

L'ancien JS SDK avait une fonction appelée FB.ensureInit. Le nouveau SDK ne semble pas avoir une telle fonction ... comment puis-je m'assurer de ne pas faire d'appels API tant qu'il n'est pas complètement lancé?

J'inclus ceci en haut de chaque page:

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

Mise à jour le 4 janvier 2012

Il semble que vous ne pouvez pas simplement appeler des méthodes dépendantes du FB (par exemple FB.getAuthResponse()) juste après FB.init() comme avant, car FB.init() semble être asynchrone maintenant. Envelopper votre code dans la réponse FB.getLoginStatus() semble faire l’astuce de détecter le moment où l’API est entièrement prête:

window.fbAsyncInit = function() {
    FB.init({
        //...
    });

    FB.getLoginStatus(function(response){
        runFbInitCriticalCode(); 
    });

};  

ou si vous utilisez fbEnsureInit() implémentation de dessous:

window.fbAsyncInit = function() {
    FB.init({
        //...
    });

    FB.getLoginStatus(function(response){
        fbApiInit = true;
    });

};  

Message d'origine:

Si vous voulez juste lancer un script quand le FB est initialisé, vous pouvez mettre une fonction de rappel dans 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
  };

Si vous voulez remplacer exactement FB.ensureInit, vous devez écrire quelque chose vous-même, car il n’ya pas de remplacement officiel (grosse erreur). Voici ce que j'utilise:

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

Usage:

fbEnsureInit(function() {
    console.log("this will be run once FB is initialized");
});
138
serg

En réalité, Facebook a déjà fourni un mécanisme pour s'abonner aux événements d'authentification.

Dans votre cas, vous utilisez " status: true ", ce qui signifie que l'objet FB demandera à Facebook le statut de connexion de l'utilisateur.

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

En appelant "FB.getLoginStatus ()", vous exécutez la même demande encore.

A la place, vous pouvez utiliser FB.Event.subscribe pour vous abonner à auth.statusChange ou Auth.authResponseChange événement [~ # ~] avant [~ # ~] vous appelez 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
});

Très probablement, en utilisant " status: false ", vous pouvez exécuter n'importe quel code juste après FB.init, car il n'y aura pas d'appels asynchrones.

35
shpoont

Voici une solution dans le cas où vous utilisez jquery et Facebook Lazy Asynchronous 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
};
12
vladaman

Un autre moyen de vérifier si le FB est initialisé consiste à utiliser le code suivant:

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

Ainsi, dans votre événement page ready, vous pouvez vérifier ns.FBInitialized et reporter l'événement à une phase ultérieure à l'aide de setTimeOut.

10
user2253630

Alors que certaines des solutions ci-dessus fonctionnent, je pensais publier notre solution éventuelle, qui définit une méthode "prête" qui sera déclenchée dès que FB sera initialisé et prêt à fonctionner. Par rapport aux autres solutions, il est avantageux de pouvoir appeler avant ou après que FB soit prêt.

Il peut être utilisé comme suit:

f52.fb.ready(function() {
    // safe to use FB here
});

Voici le fichier source (notez qu'il est défini dans un espace de noms '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
Karl Rosaen

Voici une méthode plus simple, qui ne nécessite ni événement ni délai d'attente. Cela nécessite toutefois jQuery.

Utilisez jQuery.holdReady()(documentation)

Donc, immédiatement après votre script jQuery, retardez l'événement ready.

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

Ensuite, dans votre fonction Facebook init, libérez-le:

window.fbAsyncInit = function() {
    FB.init({
        appId: '11111111111111',
        cookie: true,
        xfbml: false,
        version: 'v2.4'
    });

    // release the ready event to execute
    $.holdReady( false );
};

Ensuite, vous pouvez utiliser l'événement ready comme d'habitude:

$(document).ready( myApp.init );
4
voidstate

Au lieu d'utiliser setTimeout ou setInterval, je m'en tiendrai aux objets différés (implémentation par jQuery here ). Il est toujours difficile de résoudre la file d'attente au bon moment, car init n'a pas de rappel, mais la combinaison du résultat avec l'abonnement à un événement (comme quelqu'un l'a indiqué avant moi) devrait suffire et être suffisamment proche.

Un pseudo-extrait ressemblerait à ceci:

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();
});
4
Drachenfels

J'ai évité d'utiliser setTimeout en utilisant une fonction globale:

ÉDITER NOTE: J'ai mis à jour les scripts d'aide suivants et créé une classe plus facile à utiliser. regardez ici ::: https://github.com/tjmehta/fbExec.js

window.fbAsyncInit = function() {
    FB.init({
        //...
    });
    window.fbApiInit = true; //init flag
    if(window.thisFunctionIsCalledAfterFbInit)
        window.thisFunctionIsCalledAfterFbInit();
};

fbEnsureInit appellera son rappel après FB.init

function fbEnsureInit(callback){
  if(!window.fbApiInit) {
    window.thisFunctionIsCalledAfterFbInit = callback; //find this in index.html
  }
  else{
    callback();
  }
}

fbEnsureInitAndLoginStatus appellera son rappel après FB.init et après 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.

      }
    });
  });
}

exemple d'utilisation de fbEnsureInit:

(FB.login doit être exécuté après l'initialisation du FB)

fbEnsureInit(function(){
    FB.login(
       //..enter code here
    );
});

exemple d'utilisation de fbEnsureInitAndLogin:

(FB.api doit être exécuté après FB.init et l'utilisateur FB doit être connecté.)

fbEnsureInitAndLoginStatus(function(){
    FB.api(
       //..enter code here
    );
});
4
tjmehta

Vous pouvez vous inscrire à l'événement:

c'est à dire)

FB.Event.subscribe('auth.login', function(response) {
  FB.api('/me', function(response) {
    alert(response.name);
  });
});
2
Jonathan Tonge

Avis petits mais importants:

  1. FB.getLoginStatus Doit être appelé après FB.init, Sinon l'événement ne sera pas déclenché.

  2. vous pouvez utiliser FB.Event.subscribe('auth.statusChange', callback), mais il ne se déclenchera pas si l'utilisateur n'est pas connecté à facebook.

Voici l'exemple de travail avec les deux fonctions

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'));
2
Mher Aghabalyan

L'API Facebook surveille le FB._apiKey afin que vous puissiez le surveiller avant d'appeler votre propre application de l'API avec quelque chose comme:

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

Pas sûr que cela fasse une différence, mais dans mon cas - parce que je voulais être sûr que l'interface utilisateur était prête - j'ai terminé l'initialisation avec le document de jQuery prêt (dernier bit ci-dessus):

  $(document).ready(FBreadyState);

Notez également que je n'utilise PAS async = true pour charger le fichier all.js de Facebook, ce qui, dans mon cas, semble aider à la connexion à l'interface utilisateur et à la gestion plus fiable des fonctionnalités.

1
jimmont

Parfois, fbAsyncInit ne fonctionne pas. Je ne sais pas pourquoi et utilise cette solution de contournement alors:

 var interval = window.setInterval(function(){
    if(typeof FB != 'undefined'){
        FB.init({
            appId      : 'your ID',
            cookie     : true,  // enable cookies to allow the server to access// the session
            xfbml      : true,  // parse social plugins on this page
            version    : 'v2.3' // use version 2.3
        });

        FB.getLoginStatus(function(response) {
            statusChangeCallback(response);
        });
        clearInterval(interval);
    }
},100);
1
pax