Comment détecter quand facebook est FB.init est terminé

l'ancien SDK JS avait une fonction appelée FB.ensureInit. Le nouveau SDK ne semble pas avoir une telle fonction... Comment puis-je m'assurer que je ne fais pas d'appels api jusqu'à ce qu'il soit entièrement lancé?

Je l'inclus dans le 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>
110
demandé sur Pablo 2010-08-23 18:27:56

12 réponses

mise à Jour sur Jan 04, 2012

il semble que vous ne pouvez pas simplement appeler des méthodes dépendantes de 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 le tour de détecter quand L'API est entièrement prête:

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

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

};  

ou si vous utilisez fbEnsureInit() mise en œuvre à partir d'en bas:

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

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

};  

Original Post:

si vous voulez juste exécuter un script lorsque FB est initialisé, vous pouvez mettre une fonction de rappel à l'intérieur de 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 un remplacement exact de FB.ensureInit alors vous devriez écrire quelque chose sur votre propre comme il n'y a pas de remplacement officiel (grande erreur imo). 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");
});
136
répondu serg 2012-06-07 18:15:47

en fait Facebook a déjà fourni un mécanisme pour s'abonner aux événements d'authentification.

dans votre cas, vous utilisez " statut: true " ce qui signifie que l'objet FB demandera Facebook pour 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 requête nouveau .

à la place, vous pouvez utiliser FB.Événement.abonner pour souscrire à 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, lorsque vous utilisez " statut: false " vous pouvez exécuter n'importe quel code juste après FB.init, parce qu'il n'y aura pas d'appels asynchrones.

34
répondu shpoont 2012-12-19 11:36:57

Voici une solution dans le cas où vous utilisez et facebook chargement asynchrone paresseux:

// 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
répondu vladaman 2012-07-23 08:15:21

une autre façon de vérifier si FB a initialisé est d'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 de reporter l'événement à la phase ultérieure en utilisant setTimeOut.

9
répondu user2253630 2013-07-08 03:47:14

pendant que certaines des solutions ci - dessus fonctionnent, j'ai pensé que je poserais notre solution éventuelle-qui définit une méthode 'prête' qui va s'allumer dès que FB est initialisé et prêt à aller. Il a l'avantage sur les autres solutions qu'il est sûr d'appeler avant ou après FB est prêt.

il peut être utilisé comme ainsi:

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

voici le fichier source (notez qu'il est défini dans un 'f52.fb' espace de noms).

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
répondu Karl Rosaen 2014-06-16 19:15:08

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

modifier note: j'ai mis à jour les scripts d'aide suivants et créé une classe qui plus facile/plus simple à utiliser; vérifiez 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 callback après FB.init

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

fbEnsureInitAndLoginStatus appellera son appel 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.

      }
    });
  });
}

fbensureinit exemple d'usage:

(FB.la connexion doit être exécuté après FB a été initialisé)

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

fbEnsureInitAndLogin exemple d'usage:

(FB.l'api doit être lancée après FB.l'utilisateur init et FB doivent être connectés.)

fbEnsureInitAndLoginStatus(function(){
    FB.api(
       //..enter code here
    );
});
4
répondu tjmehta 2012-04-25 05:34:45

Voici une méthode plus simple, qui ne nécessite ni événements ni délais. Il ne nécessite jQuery, cependant.

utiliser jQuery.holdReady() (docs)

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

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

puis, dans votre fonction init Facebook, relâchez-le:

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

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

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

$(document).ready( myApp.init );
4
répondu voidstate 2015-09-09 09:55:08

au lieu d'utiliser un setTimeout ou un setInterval, Je m'en tiendrais aux objets différés (implémentation par jQuery ici ). Il est encore difficile de résoudre la file d'attente au bon moment, car init n'a pas de callbacks mais combiner le résultat avec l'abonnement d'événement (comme quelqu'un l'a souligné avant moi), devrait faire l'affaire et être assez proche.

Pseudo-snippet 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();
});
3
répondu Drachenfels 2013-01-26 08:51:52

Le Facebook de l'API de montres pour le FB._apiKey donc vous pouvez regarder pour cela 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();
}; 

Je ne suis 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 enveloppé l'initialisation avec le document de jQuery prêt (dernier bit ci-dessus):

  $(document).ready(FBreadyState);

Notez aussi que je n'utilise pas async = true pour charger le tout de Facebook.js, qui dans mon cas semble aider à la signature dans L'UI et les caractéristiques de conduite plus fiable.

1
répondu jimmont 2012-04-11 21:31:47

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

ie)

FB.Event.subscribe('auth.login', function(response) {
  FB.api('/me', function(response) {
    alert(response.name);
  });
});
1
répondu Jonathan Tonge 2012-06-10 03:28:22

parfois fbAsyncInit ne fonctionne pas. Je ne sais pas pourquoi et utiliser cette solution 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
répondu pax 2015-06-18 13:43:02

Petit mais IMPORTANT:

  1. FB.getLoginStatus doit être appelé après FB.init , sinon il ne sera pas le feu de l'événement.

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

Voici l'exemple de fonctionnement 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'));
1
répondu Mher Aghabalyan 2016-09-13 23:04:43