我不必为 GoogleAuth 库检索单例并在我的登录页面控制器中设置客户端,而是必须在 index.html 文件中对其进行初始化:
<script src="https://apis.google.com/js/api:client.js?onload=start" async defer></script>
<script>
function start() {
gapi.load('auth2', function() {
auth2 = gapi.auth2.init({
client_id: 'myAppID',
cookiepolicy: 'single_host_origin'
});
});
}
</script>
这解决了注销问题。但是,如果刷新登录页面,其控制器逻辑将在定义 gapi.auth2 之前执行,并且无法成功地将点击处理程序附加到登录按钮。
为了避免这种情况 - 虽然不是一个优雅的解决方案 - 我使用 $interval 等到 gapi.auth2 被初始化:
waitForAuth2Initialization = $interval(function () {
console.log("Checking...");
if (!gapi.auth2)
return;
console.log("Ok, gapi.auth2 is not undefined anymore");
var auth2 = gapi.auth2.getAuthInstance();
// Attach signin
auth2.attachClickHandler...
$interval.cancel(waitForAuth2Initialization);
}, 50);
编辑:另一种可能的解决方案是使用控制器逻辑的承诺回调来等待承诺解决,即直到 Google API 完全加载并且 gapi.auth2 准备好使用。
可以通过以下方式实现:
<script src="https://apis.google.com/js/api:client.js?onload=start" async defer></script>
<script>
gapiPromise = (function () {
var deferred = $.Deferred();
window.start = function () {
deferred.resolve(gapi);
};
return deferred.promise();
}());
auth2Promise = gapiPromise.then(function () {
var deferred = $.Deferred();
gapi.load('auth2', function () {
auth2 = gapi.auth2.init({
client_id: 'myAppID',
cookiepolicy: 'single_host_origin'
}).then(function () {
deferred.resolve(gapi.auth2);
});
});
return deferred.promise();
});
</script>
然后在控制器中:
auth2Promise.then(function () {
console.log("Ok, gapi.auth2 is not undefined anymore");
var auth2 = gapi.auth2.getAuthInstance();
// Attach signin
auth2.attachClickHandler...
});
但是,这种方法的缺点是它比使用$interval 的第一个方法慢(附加点击处理程序花费的时间是第一个的两倍)。