gapi is not defined - Google sign in issue with gapi.auth2.init

后端 未结 6 1501
死守一世寂寞
死守一世寂寞 2020-11-29 05:07

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?



        
相关标签:
6条回答
  • 2020-11-29 05:34

    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.

    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.

    0 讨论(0)
  • 2020-11-29 05:34

    For a Vue.JS app

    • 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.

    Here's a fairly complete example you can just paste into a new vue-cli project.

    Don't forget to supply your own client ID!

    public/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>
    
    
    
    0 讨论(0)
  • 2020-11-29 05:36

    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.load('auth2', initSigninV2);
    
    function initSigninV2() {
        gapi.auth2.init({
            client_id: 'CLIENT_ID.apps.googleusercontent.com'
        }).then(function (authInstance) {
            // now auth2 is fully initialized
        });
    }
    
    0 讨论(0)
  • 2020-11-29 05:36

    This worked for me: https://stackoverflow.com/a/55314602/1034622

    Include this script tag

    <script src="https://apis.google.com/js/platform.js"></script>
    
    0 讨论(0)
  • 2020-11-29 05:40

    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();
      }
    }
    
    0 讨论(0)
  • 2020-11-29 05:46

    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...

    To wait for gapi before executing this code you can use onload query param in script tag, like following:

    <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 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
      });
    });
    
    0 讨论(0)
提交回复
热议问题