Facebook登录弹窗被阻止

31

我正在使用Facebook登录功能,但遇到的问题是,如果在页面媒体加载完成之前点击Facebook登录按钮,它会阻止弹出式窗口进行Facebook登录,但如果我在等待一秒钟后再点击fblogin,则可以正常运行。

这是我正在使用的函数:

function fb_login() {
var email='';
console.log(loginClassbackQueue);
// console.log('user wants to login with fb');
FB.getLoginStatus(function(response) {
    if(response.status!='connected'){
        FB.login(function(response) {
            // console.log(response);
            if (response.authResponse) {
                // console.log('user logged in successfully');
                // console.log(response);
                email = update_f_data_login(response);
                $('#fb_login_popup, #popup_overlay').hide();
                // loginme(email);
                } 
            else {
                    loginClassbackQueue = [];
                // console.log('user failed to login');
                }
                // console.log('fb login completed successfully');
            }, {scope:"email,user_birthday,user_likes,user_location,friends_likes,publish_actions"}
        );
        }
    else{
    // console.log('logged in and connected');
    email = update_f_data_login(response);
    $('#fb_login_popup, #popup_overlay').hide();
    }

});

}

当我在这个网站http://fab.com/上执行相同的操作时,它总是打开弹窗,从不阻止弹窗。

4个回答

56

您不能在FB.getLoginStatus的回调函数中调用FB.login

如果弹出窗口不是在用户单击操作的直接结果下生成的,则浏览器往往会阻止弹出窗口。

由于FB.getLoginStatus执行了ajax调用,并且您在其响应上调用了FB.login,这个调用会导致打开的弹出窗口被阻止

解决您的问题的方法是在页面加载时调用FB.getLoginStatus并在fb_login()方法中使用响应。


2
该解决方案仅在用户加载页面时已登录 Facebook 时才有效。否则会失败。 - Jake Wilson
9
并不完全正确。从FB.getLoginStatus的回调函数中调用FB.login是可以的,并且在许多情况下,这正是正确的做法。你只需要确信登录状态已经被加载。最明显的方法是在FB.init的选项对象中指定status: true,但其他方式包括使用FB.getLoginStatusFB.loginFB.ui(技术上所有这些选项都使用了FB.ui)并且异步过程必须完成。你还应该确保不要为第二个参数指定true,例如FB.getLoginStatus(..., true); - AndrewF
此外,调用FB.login必须是从点击事件中的第一个调用。在两个之间的任何调用堆栈都会导致“弹出阻止”。 - Sharjeel Ahmed
我正在从AJAX的成功响应中调用fb登录,我通过这里的答案解决了它。谢谢。 - Mr Megamind
AndrewF的一个很好的技巧 - Sérgio S. Filho
显示剩余2条评论

41

只要您确信已经在内部加载了登录状态,就可以在FB.getLoginStatus的回调中调用FB.login,这样做是完全没有问题的。为此,请使用以下任一方法之一:

  • FB.init({..., status: true, ... })
  • FB.getLoginStatus(...)
  • FB.login(...)
  • FB.ui(...)

从技术上讲,所有这些选项都使用FB.ui。异步过程必须完成,可能需要几秒钟的时间。只要您已经使用上述某种方法之一进行了与FB的跨域调用,并且该异步过程已经完成,获取登录状态将不会发出异步调用,并且弹出窗口也不会被阻止。

您还应确保不要为第二个参数指定true,例如:FB.getLoginStatus(..., true);


7
我认为这个应该标记为正确的解决方案。 - Nimeshka Srimal
将FB.getLoginStatus(...,true)的第二个参数设置为true将在桌面Chrome中调用弹出窗口阻止程序;仅在需要特殊处理URL回调登录以强制缓存的情况下使用它(例如:对于Chrome iOS中的Facebook登录)。 - morph85
因此,“你也应该确保不指定为true”。 - AndrewF
感谢@AndrewF,通过在FB.init中传递true参数,我可以使用getLoginStatus作为回调函数,并且它不会阻止弹出窗口。 - Anshul Mishra

13

请确保将status设置为true,这将解决弹出窗口阻止程序的问题。

window.fbAsyncInit = function() {
  FB.init({
    appId      : '{your-app-id}',
    cookie     : true,  // enable cookies to allow the server to access 
                        // the session
    xfbml      : true,  // parse social plugins on this page
    version    : 'v2.5', // use graph api version 2.5
    status     : true // set this status to true, this will fixed popup blocker issue
  });

1
这对我有用...状态选项的文档说它确定用户当前登录状态是否在每个页面加载时刷新。如果禁用此选项,则必须使用.getLoginStatus()手动检索该状态。默认为false。 虽然我对它实际上是做什么有一点想法...但无论用户是否在fb上登录,都可以正常工作... - Rishabh

1
我遇到了同样的问题,让我苦恼了三天。我尝试了上述提到的解决方案,在Firefox和Edge中都有效,但在Chrome中,无论我做什么,仍然会被阻止。另一个问题是,当我从按钮按下事件中调用函数时,登录对话框没有被阻止,但在登录对话框关闭后,它没有得到任何响应,因此我被卡住了。所以我的解决方案如下,但你不需要按登录按钮,它将重定向到FB登录页面,而无需按下按钮事件,并在返回后继续进行所有其他sdk步骤。只需将此代码添加到您的代码中,看看它是否有帮助,然后根据您的需要进行调整。
function statusChangeCallback(response) {
            console.log('statusChangeCallback');
            console.log(response);


            // The response object is returned with a status field that lets the
            // app know the current login status of the person.
            // Full docs on the response object can be found in the documentation
            // for FB.getLoginStatus().
            if (response.status === 'connected') {
                // Logged into your app and Facebook.
                document.getElementById('Image2').style.display = "none";
                document.getElementById('mail').style.display = "in-line";

                testAPI();
            } else {
                // The person is not logged into your app or we are unable to tell.
                window.alert("Faça login no facebook antes de continuar - Obrigado");
                window.location.href = 'https://www.facebook.com/dialog/oauth' +
                '?client_id=55215442252214521548' +
                '&scope=public_profile,email,user_friends' +
                '&redirect_uri=' + encodeURIComponent(document.URL);
                document.getElementById('Image2').style.visibility = "hidden";
                document.getElementById('mail').style.display = "in-line";

            }
        }

        // This function is called when someone finishes with the Login
        // Button.  See the onlogin handler attached to it in the sample
        // code below.
        function checkLoginState() {
            FB.getLoginStatus(function (response) {
                statusChangeCallback(response);

            });
        } 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接