AngularJS中出现FB.login()早于FB.init()调用的错误如何解决?
解决AngularJS中FB.login()调用时出现"FB.login() called before FB.init()"的问题
这个错误的核心原因很明确:你的代码在Facebook SDK完成初始化(也就是FB.init()执行完毕)之前,就调用了FB.login()。因为Facebook SDK是异步加载的,而Angular的控制器可能在SDK加载完成前就已经初始化并触发了登录操作。
下面是一步步的修复方案,亲测有效:
1. 补全并调整Facebook SDK的加载代码
首先要确保SDK的加载脚本完整,并且我们在初始化完成后通知Angular应用:
<html ng-app="faceBoookLogin"> <head> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script> </head> <body> <!-- 你的登录按钮,绑定到控制器方法 --> <div ng-controller="FbLoginController"> <button ng-click="loginWithFacebook()">Login with Facebook</button> </div> <!-- 加载你的Angular控制器脚本 --> <script type="text/javascript" src="fbController.js"></script> <!-- 完整的Facebook SDK加载逻辑 --> <script type="text/javascript"> window.fbAsyncInit = function() { FB.init({ appId : 'your-app-id', // 替换成你自己的Facebook应用ID autoLogAppEvents : true, xfbml : true, version : 'v2.12' }); // SDK初始化完成后,触发自定义事件通知Angular angular.element(document).ready(function() { angular.element(document).trigger('fb:init'); }); }; // 异步加载Facebook 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"; fjs.parentNode.insertBefore(js, fjs); }(document, 'script', 'facebook-jssdk')); </script> </body> </html>
2. 用Angular服务封装Facebook登录逻辑
我们创建一个专门的服务来处理Facebook的初始化状态和登录操作,确保只有在SDK准备好后才执行登录:
angular.module('faceBoookLogin', []) // 封装Facebook认证逻辑的服务 .service('FacebookAuthService', ['$rootScope', function($rootScope) { let isSdkReady = false; // 监听SDK初始化完成的自定义事件 angular.element(document).on('fb:init', function() { isSdkReady = true; $rootScope.$apply(); // 通知Angular更新状态 }); // 登录方法,返回Promise处理异步结果 this.login = function() { return new Promise((resolve, reject) => { if (!isSdkReady) { return reject(new Error('Facebook SDK 还没准备好,请稍后再试')); } // 调用FB.login,传入需要的权限 FB.login(response => { if (response.authResponse) { resolve(response); } else { reject(new Error('用户取消登录或登录失败')); } }, { scope: 'public_profile,email' }); // 可根据需求调整权限 }); }; }]) // 登录控制器 .controller('FbLoginController', ['$scope', 'FacebookAuthService', function($scope, FacebookAuthService) { $scope.loginWithFacebook = function() { FacebookAuthService.login() .then(response => { console.log('登录成功:', response); // 这里可以继续调用FB.api获取用户信息 FB.api('/me', { fields: 'name,email' }, userInfo => { console.log('用户信息:', userInfo); // 处理用户信息,比如存入本地或发送到后端 }); }) .catch(error => { console.error('登录出错:', error); // 给用户显示错误提示 }); }; }]);
关键注意点
- 替换appId:一定要把代码里的
your-app-id换成你在Facebook开发者平台创建的应用ID。 - 权限设置:
scope参数里的权限根据你的业务需求调整,比如不需要email就可以去掉。 - 域名白名单:在Facebook开发者后台的"设置"->"基本"里,确保你的测试/生产域名添加到了"网站域名"列表里,否则会出现跨域错误。
这样调整后,登录操作只会在FB.init完成后执行,就不会再出现FB.login() called before FB.init()的错误了。
内容的提问来源于stack exchange,提问作者Kapil Soni
相关产品推荐
相关产品推荐

