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>
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");
});
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.
Voici une solution dans le cas où vous utilisez jQuery 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
};
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.
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
};
})();
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
);
});
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 );
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();
});
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.
Vous pouvez vous abonner à l'événement:
ie)
FB.Event.subscribe('auth.login', function(response) {
FB.api('/me', function(response) {
alert(response.name);
});
});
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);
Petit mais IMPORTANT:
-
FB.getLoginStatus
doit être appelé aprèsFB.init
, sinon il ne sera pas le feu de l'événement. -
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'));