我使用Facebook作为我网站的会员制。它使用代码生成登录控件,允许用户通过他们的Facebook帐户登录。如果他们已经是会员,那基本上就是一次点击;如果他们不是,那就是2次点击(用于授予权限)。
我遇到了问题...反馈表明登录按钮并不总是正确加载。它不是加载facebook登录控件,而是简单地说明(在文本中)“通过facebook登录” - 如果控件成功加载,这就是登录按钮会说的。
测试表明,当facebook javascript SDK无法完全加载(无论出于何种原因)时会发生这种情况。我见过url中的#阻止SDK加载的实例。
为了更好地支持这个问题,我将如何检测facebook javascript SDK是否已加载并准备好了?这样,如果它失败了,我可以为用户留下某种注意事项。
以下是它当前添加到页面的方式:
<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>
答案 0 :(得分:47)
您应该加载Javascript Library Asynchronously并将所有与FB相关的函数放在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>
此代码异步加载SDK,因此不会阻止加载 您网页的其他元素。这对于确保尤为重要 为用户和SEO机器人加载快速页面。
上述代码中的URL是协议相对的。这让我们 浏览器通过与之相同的协议(HTTP或HTTPS)加载SDK 包含页面,这将阻止“不安全内容”警告。
分配给
window.fbAsyncInit
的功能在SDK完成后立即运行 已加载。加载SDK后要运行的任何代码 应该放在这个函数中,并在调用FB.init
之后。 例如,this is where you would test the logged in status 用户或您的应用程序所在的subscribe to any Facebook events 感兴趣。
以下是一个简单的例子:
<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>
(只需点击check
链接几次)
请注意,您仍然可以构建Login Link服务器端和 WITHOUT JavaScript。使用PHP-SDK的示例:
$loginUrl = $facebook->getLoginUrl();
...
...
<a href="<?php echo $loginUrl; ?>">
<img src="http://static.ak.fbcdn.net/rsrc.php/zB6N8/hash/4li2k73z.gif">
</a>
答案 1 :(得分:8)
加载SDK时触发事件:
window.fbAsyncInit = function() {
FB.init({appId: "#{KeyManager.facebook_app_id}", status: true, cookie: true, xfbml: true});
jQuery('#fb-root').trigger('facebook:init');
};
听听这样的事件:
$("#fb-root").bind("facebook:init", function() {
..
});
答案 2 :(得分:4)
在加载FB JS SDK同步/异步后,只需查看FB对象:
if (typeof FB !== 'undefined') {
alert("FB JS API is available now");
} else {alert("do something...")}
这是一个足够的检查,可以安全地调用任何与Facebook JS API相关的方法。
答案 3 :(得分:3)
这个JS文件引入了什么全局变量?
假设它创建了一个
var FaceBook = function() {//make friends! Or whatever...}
您可以测试if (FaceBook)
并从那里开始。
很可能他们会在启动框架时为你提供某种加载事件,可以这么说。
答案 4 :(得分:3)
根据此页面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');
}
});
答案 5 :(得分:2)
如果您正在使用jQuery(并且在FB初始化之前已经加载了jQuery),则可以使用Deferred来运行其他初始化。
<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>
然后在其他地方(在JS文件中)你可以这样做(实际上这个方法的关键是你可以把它放在你想要的任意数量的地方,它们都会被触发):
window.fbLoaded.done(function () { alert('FB initialized'); });
注意:如果初始化完成,则在添加done
事件之前,它将立即触发(这是Deferreds的工作方式)。所以你可以把它放在任何你想要的地方。
如果API从未初始化,请务必测试您希望行为是什么(只需注释掉(function(d,s,id)... part
答案 6 :(得分:2)
// 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 ...
});
答案 7 :(得分:0)
动态加载脚本(从js添加脚本标记)并检查错误/成功事件。
答案 8 :(得分:0)
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]);
}
});
}
如果你想从另一个javascript检查状态(建议@Leo Romanovsky)
$("#fb-root").on("facebook:init", function(event, response) {
if(response.status === 'connected') {
alert("logged with FB")
}else{
alert("No Logged with FB")
}
});
答案 9 :(得分:0)
我几天就用这个:
var isLoaded = false;
$(document).on('DOMSubtreeModified', function () {
if ($('#fb-root').length && !isLoaded) {
isLoaded = true;
// ...
}
});
您怎么看?
答案 10 :(得分:0)
如其他答案所述;感谢@ifaour&amp; @Leo Romanovsky;检测SDK是否已成功加载的最佳方法是在调用fbAsyncInit时触发事件。
如果捕获事件,则加载SDK。下面的代码显示了如何实现这一目标:
<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.");
});
});
如果事件未被触发,您可以添加一个计时器来检查FB对象是否为“未定义”并显示相应的消息。
注1:在此事件被解雇之前可能会有一点延迟。
注2:“反馈表明登录按钮并不总是正确加载”。我知道FFv49私密浏览阻止了对fb的调用。