Javascript gapi 未定义 - 谷歌登录问题 gapi.auth2.init
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31144874/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
gapi is not defined - Google sign in issue with gapi.auth2.init
提问by Jon Tan
I'm trying to implement Google Sign In and retrieve the profile information of the user. The error is: Uncaught ReferenceError: gapi is not defined. Why is that?
我正在尝试实施 Google 登录并检索用户的个人资料信息。错误是:Uncaught ReferenceError: gapi is not defined。这是为什么?
<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://apis.google.com/js/platform.js" async defer></script>
<script type="text/javascript">
$(function(){
gapi.auth2.init({
client_id: 'filler_text_for_client_id.apps.googleusercontent.com'
});
});
</head>
<body>
</body>
</html>
回答by Bogdan Savluk
It happens because you have async
and defer
attributes on your script tag. gapi
would be loaded after your script tag with gapi.auth2.init
...
发生这种情况是因为您的脚本标签上有async
和defer
属性。gapi
将在您的脚本标记之后加载gapi.auth2.init
...
To wait for gapi
before executing this code you can use onload query param in script tag, like following:
要gapi
在执行此代码之前等待,您可以在脚本标签中使用 onload 查询参数,如下所示:
<script src="https://apis.google.com/js/platform.js?onload=onLoadCallback" async defer></script>
<script>
window.onLoadCallback = function(){
gapi.auth2.init({
client_id: 'filler_text_for_client_id.apps.googleusercontent.com'
});
}
</script>
Or for case when you need it in many places, you can use promises to better structure it:
或者如果你在很多地方都需要它,你可以使用 promise 来更好地构建它:
// promise that would be resolved when gapi would be loaded
var gapiPromise = (function(){
var deferred = $.Deferred();
window.onLoadCallback = function(){
deferred.resolve(gapi);
};
return deferred.promise()
}());
var authInited = gapiPromise.then(function(){
gapi.auth2.init({
client_id: 'filler_text_for_client_id.apps.googleusercontent.com'
});
})
$('#btn').click(function(){
gapiPromise.then(function(){
// will be executed after gapi is loaded
});
authInited.then(function(){
// will be executed after gapi is loaded, and gapi.auth2.init was called
});
});
回答by Kelly Ellis
I think you'll find with the above example that this won't work either, as gapi.auth2
will not yet be defined (I know this because I made the same mistake myself, today) You first need to call gapi.load('auth2', callback)
and pass THAT a callback which then calls gapi.auth2.init
. Here is an example of my _onGoogleLoad
function, which is the callback for loading the first platform.js
script.
我想你会发现在上面的例子中这也不起作用,因为gapi.auth2
还没有定义(我知道这一点,因为我今天自己犯了同样的错误)你首先需要调用gapi.load('auth2', callback)
并传递一个回调,然后调用gapi.auth2.init
。这是我的_onGoogleLoad
函数的一个例子,它是加载第一个platform.js
脚本的回调。
var _auth2
var _onGoogleLoad = function () {
gapi.load('auth2', function () {
_auth2 = gapi.auth2.init({
client_id: 'OUR_REAL_ID_GOES_HERE',
scope: 'email',
fetch_basic_profile: false
})
_enableGoogleButton()
})
}
After that, you can use the _auth2
variable to actually sign users in.
之后,您可以使用该_auth2
变量实际登录用户。
回答by bora89
The problem is not only in gapi
. To call init
method - auth2 object must be initialized.
There is a promise once a google auth object is in fully initialized GoogleAuth.then(onInit, onFailure)
问题不仅在于gapi
. 要调用init
方法 - 必须初始化 auth2 对象。一旦 google auth 对象完全初始化,就有一个承诺GoogleAuth.then(onInit, onFailure)
gapi.load('auth2', initSigninV2);
function initSigninV2() {
gapi.auth2.init({
client_id: 'CLIENT_ID.apps.googleusercontent.com'
}).then(function (authInstance) {
// now auth2 is fully initialized
});
}
回答by Miha Pirnat
While these answers helped me, I believe there is better answer in official docs.
虽然这些答案对我有所帮助,但我相信官方文档中有更好的答案。
See Integrating Google Sign-In using listeners
var auth2; // The Sign-In object.
var googleUser; // The current user.
/**
* Calls startAuth after Sign in V2 finishes setting up.
*/
var appStart = function() {
gapi.load('auth2', initSigninV2);
};
/**
* Initializes Signin v2 and sets up listeners.
*/
var initSigninV2 = function() {
auth2 = gapi.auth2.init({
client_id: 'CLIENT_ID.apps.googleusercontent.com',
scope: 'profile'
});
// Listen for sign-in state changes.
auth2.isSignedIn.listen(signinChanged);
// Listen for changes to current user.
auth2.currentUser.listen(userChanged);
// Sign in the user if they are currently signed in.
if (auth2.isSignedIn.get() == true) {
auth2.signIn();
}
// Start with the current live values.
refreshValues();
};
/**
* Listener method for sign-out live value.
*
* @param {boolean} val the updated signed out state.
*/
var signinChanged = function (val) {
console.log('Signin state changed to ', val);
document.getElementById('signed-in-cell').innerText = val;
};
/**
* Listener method for when the user changes.
*
* @param {GoogleUser} user the updated user.
*/
var userChanged = function (user) {
console.log('User now: ', user);
googleUser = user;
updateGoogleUser();
document.getElementById('curr-user-cell').innerText =
JSON.stringify(user, undefined, 2);
};
/**
* Updates the properties in the Google User table using the current user.
*/
var updateGoogleUser = function () {
if (googleUser) {
document.getElementById('user-id').innerText = googleUser.getId();
document.getElementById('user-scopes').innerText =
googleUser.getGrantedScopes();
document.getElementById('auth-response').innerText =
JSON.stringify(googleUser.getAuthResponse(), undefined, 2);
} else {
document.getElementById('user-id').innerText = '--';
document.getElementById('user-scopes').innerText = '--';
document.getElementById('auth-response').innerText = '--';
}
};
/**
* Retrieves the current user and signed in states from the GoogleAuth
* object.
*/
var refreshValues = function() {
if (auth2){
console.log('Refreshing values...');
googleUser = auth2.currentUser.get();
document.getElementById('curr-user-cell').innerText =
JSON.stringify(googleUser, undefined, 2);
document.getElementById('signed-in-cell').innerText =
auth2.isSignedIn.get();
updateGoogleUser();
}
}
回答by counterbeing
For a Vue.JS app
对于 Vue.JS 应用程序
- Add an onload hook to the script tag for
platform.js
- Set up a function that dispatches an event
- Catch that event in the
mounted
hook of your component.
- 为脚本标签添加一个 onload 钩子
platform.js
- 设置一个分派事件的函数
- 在
mounted
组件的钩子中捕获该事件。
Here's a fairly complete example you can just paste into a new vue-cli
project.
这是一个相当完整的示例,您可以将其粘贴到新vue-cli
项目中。
Don't forget to supply your own client ID!
不要忘记提供您自己的客户 ID!
public/index.html
公共/index.html
<script type="text/javascript">
function triggerGoogleLoaded() {
window.dispatchEvent(new Event("google-loaded"));
}
</script>
<script
src="https://apis.google.com/js/platform.js?onload=triggerGoogleLoaded"
async
defer
></script>
<meta
name="google-signin-client_id"
content="xxxxxxxxxxxx.apps.googleusercontent.com"
/>
App.vue
应用程序
<template>
<div id="app">
<div id="nav">
<div id="google-signin-btn"></div>
<a href="#" class="sign-out" @click="signOut" v-if="profile">Sign out</a>
</div>
<div v-if="profile" class="">
<h2>Signed In User Profile</h2>
<pre>{{ profile }}</pre>
</div>
<div v-if="!profile">
<h2>Signed out.</h2>
</div>
<router-view />
</div>
</template>
<script>
export default {
components: {},
data() {
return {
profile: false
};
},
methods: {
onSignIn(user) {
const profile = user.getBasicProfile();
this.profile = profile;
},
signOut() {
var auth2 = gapi.auth2.getAuthInstance();
auth2.signOut().then(() => {
location.reload(true);
});
},
renderGoogleLoginButton() {
gapi.signin2.render("google-signin-btn", {
onsuccess: this.onSignIn
});
}
},
mounted() {
window.addEventListener("google-loaded", this.renderGoogleLoginButton);
}
};
</script>
回答by Pablo Chvx
This worked for me: https://stackoverflow.com/a/55314602/1034622
这对我有用:https: //stackoverflow.com/a/55314602/1034622
Include this script tag
包括这个脚本标签
<script src="https://apis.google.com/js/platform.js"></script>