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

Jon Tan picture Jon Tan · Jun 30, 2015 · Viewed 73.1k times · Source

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?

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

Answer

Bogdan Savluk picture Bogdan Savluk · Jun 30, 2015

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
  });
});