Как определить, когда FB facebook.init-это полное
в старом JS SDK была функция с именем FB.обеспечьте это. Новый SDK, похоже, не имеет такой функции... как я могу гарантировать, что я не делаю вызовы api, пока он не будет полностью инициирован?
Я включить это в верхней части каждой страницы:
<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 ответов:
обновление от 04 января 2012 года
похоже, что вы не можете просто вызвать FB-зависимые методы (например
FB.getAuthResponse()
) сразу послеFB.init()
как и раньше, какFB.init()
кажется, теперь асинхронный. Обертывание кода вFB.getLoginStatus()
ответ, кажется, делает трюк обнаружения, когда API полностью готов:window.fbAsyncInit = function() { FB.init({ //... }); FB.getLoginStatus(function(response){ runFbInitCriticalCode(); }); };
или
fbEnsureInit()
реализация от ниже:window.fbAsyncInit = function() { FB.init({ //... }); FB.getLoginStatus(function(response){ fbApiInit = true; }); };
Исходный Пост:
если вы хотите просто запустить какой-то скрипт, когда FB инициализируется, вы можете поместить некоторую функцию обратного вызова внутри
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 };
если вы хотите точную замену FB.ensureInit тогда вам придется написать что-то самостоятельно, так как нет официальной замены (большая ошибка imo). Вот что я использую:
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(); } } }
использование:
fbEnsureInit(function() { console.log("this will be run once FB is initialized"); });
На самом деле Facebook уже предоставил механизм для подписки на события аутентификации.
в вашем случае вы используете "статус: true " это означает, что объект FB запросит Facebook для статуса входа пользователя.
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.getLoginStatus () " вы выполняете тот же запрос снова.
вместо этого вы могли бы использовать FB.Событие.подписаться подписаться auth.statusChange или auth.authResponseChange событие до вы звоните 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 });
скорее всего, при использовании "статус: false " вы можете запустить любой код сразу после FB.init, потому что не будет асинхронных вызовов.
вот решение в случае, если вы используете jquery и Facebook асинхронная ленивая загрузка:
// 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 };
другой способ проверить, инициализирован ли FB, - это использовать следующий код:
ns.FBInitialized = function () { return typeof (FB) != 'undefined' && window.fbAsyncInit.hasRun; };
таким образом, в вашем событии готовности страницы вы можете проверить ns.FBInitialized и отложить событие на более позднюю фазу с помощью setTimeOut.
хотя некоторые из вышеперечисленных решений работают, я думал, что опубликую наше окончательное решение, которое определяет "готовый" метод, который будет срабатывать, как только FB будет инициализирован и готов к работе. Он имеет преимущество перед другими решениями, что безопасно звонить до или после того, как FB будет готов.
его можно использовать так:
f52.fb.ready(function() { // safe to use FB here });
вот исходный файл (обратите внимание, что он определен в 'f52.ФБ' пространство имен).
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 }; })();
я избегал использования setTimeout с помощью глобальной функции:
EDIT Примечание: я обновил следующие вспомогательные скрипты и создал класс, который проще / проще в использовании; проверьте его здесь :::https://github.com/tjmehta/fbExec.js
window.fbAsyncInit = function() { FB.init({ //... }); window.fbApiInit = true; //init flag if(window.thisFunctionIsCalledAfterFbInit) window.thisFunctionIsCalledAfterFbInit(); };
fbEnsureInit вызовет его обратный вызов после FB.init
function fbEnsureInit(callback){ if(!window.fbApiInit) { window.thisFunctionIsCalledAfterFbInit = callback; //find this in index.html } else{ callback(); } }
fbEnsureInitAndLoginStatus вызовет его обратный вызов после FB.init и после ФБ.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:
(FB.логин должен быть запущен после инициализации FB)
fbEnsureInit(function(){ FB.login( //..enter code here ); });
fbEnsureInitAndLogin пример использования:
(FB.api должен быть запущен после FB.пользователь init и FB должен войти в систему.)
fbEnsureInitAndLoginStatus(function(){ FB.api( //..enter code here ); });
вот более простой метод, который не требует ни событий, ни таймаутов. Однако для этого требуется jQuery.
использовать
jQuery.holdReady()
(docs)Итак, сразу после вашего сценария jQuery задержите готовое событие.
<!-- 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>
затем, в вашей функции Facebook init, отпустите его:
window.fbAsyncInit = function() { FB.init({ appId: '11111111111111', cookie: true, xfbml: false, version: 'v2.4' }); // release the ready event to execute $.holdReady( false ); };
затем вы можете использовать готовое событие как обычно:
$(document).ready( myApp.init );
вместо использования любого setTimeout или setInterval я бы придерживался отложенных объектов (реализация jQuery здесь). Все еще сложно решить очередь в нужный момент, потому что у init нет обратных вызовов, но объединение результата с подпиской на событие (как кто-то указал передо мной) должно сделать трюк и быть достаточно близко.
псевдо-фрагмент будет выглядеть следующим образом:
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(); });
API Facebook наблюдает за FB._apiKey так что вы можете следить за этим перед вызовом собственного приложения API с чем-то вроде:
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(); };
не уверен, что это имеет значение, но в моем случае-потому что я хотел убедиться, что пользовательский интерфейс был готов-я завернул инициализацию с готовым документом jQuery (последний бит выше):
$(document).ready(FBreadyState);
обратите внимание, что я не использую async = true для загрузки всех Facebook.js, который в моем случае, кажется, помогает при входе в систему пользовательский интерфейс и функции вождения более надежно.
вы можете подписаться на события:
ie)
FB.Event.subscribe('auth.login', function(response) { FB.api('/me', function(response) { alert(response.name); }); });
иногда fbAsyncInit не работает. Я не знаю, почему и использовать этот метод, то:
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);
небольшие, но важные уведомления:
FB.getLoginStatus
должен быть вызван послеFB.init
, в противном случае он не будет запускать событие.можно использовать
FB.Event.subscribe('auth.statusChange', callback)
, но он не будет срабатывать, когда пользователь не выполнил вход в facebook.вот рабочий пример с обеими функциями
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'));