8

A previous question here got me most of the way (hopefully) to getting this working, but I can't seem to get a Google API working from TypeScript. I'm basically following this example: https://developers.google.com/api-client-library/javascript/samples/samples

I'm not seeing an error, the method to run the API call just isn't getting fired.

I've installed the typings for gapi and gapi.auth. initClient() doesn't throw any errors, it just never seems to complete. The current user is signed in as a Google user, but not authorized for the API call yet. That's the next thing I was going to deal with, but right now the call isn't even being made. As you can see below, I added a logging line at the beginning of the method that isn't being called.

initGapiClient() {
    gapi.load('client:auth2', this.initClient);
  }

  initClient() {
    gapi.client.init({
      apiKey: '',
      discoveryDocs: ['https://www.googleapis.com/discovery/v1/apis/youtube/v3/rest'],
      clientId: 'xxxxxx.apps.googleusercontent.com',
      scope: 'https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.readonly'
    }).then(function () {
      // Listen for sign-in state changes.
    gapi.auth2.getAuthInstance().isSignedIn.listen(this.updateSigninStatus);

      // Handle the initial sign-in state.
      this.updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
    });
  }

  updateSigninStatus(isSignedIn) {
    if (isSignedIn) {
      this.listPlaylists();
    } else {
      alert("Can't sign in");          
    }
  }

  listPlaylists() {
    console.log("Called listPlaylists");
    ... 
    API call here
    ... 
  }
eko
  • 39,722
  • 10
  • 72
  • 98
beachCode
  • 3,202
  • 8
  • 36
  • 69
  • How do I install the typings for gapi and gapi.auth? – Plastic Feb 28 '18 at 09:45
  • @Plastic npm install --save @types/gapi and also @types/gapi.auth2. Just Google it, you'll find these: https://www.npmjs.com/package/@types/gapi.auth2 – beachCode Mar 02 '18 at 00:01

2 Answers2

5

Change

.then(function () {
      // Listen for sign-in state changes.
    gapi.auth2.getAuthInstance().isSignedIn.listen(this.updateSigninStatus);

      // Handle the initial sign-in state.
      this.updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
    });

to

.then(()=> {
      // Listen for sign-in state changes.
    gapi.auth2.getAuthInstance().isSignedIn.listen(this.updateSigninStatus.bind(this));

      // Handle the initial sign-in state.
      this.updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
    });

if you use function your this will not refer to your component and passing a function as a parameter like .listen(this.updateSigninStatus); will also make the outer this to be binded to this function.

I suggest you to read: How to access the correct `this` context inside a callback?

Community
  • 1
  • 1
eko
  • 39,722
  • 10
  • 72
  • 98
  • Thanks, I'll take a look at that link. I tried the change you suggested, but it hasn't resolved the problem. Anything inside "then" is still not being called. Even `console.log()` isn't being triggered. Postman shows the GET call to the discoveryDoc is working. – beachCode Apr 21 '17 at 06:38
  • @beachCode if you are using chrome, you can check from the network tab in the developer tools (F12) to see whether it is actually making the request or not. – eko Apr 21 '17 at 07:11
  • @echonax `.listen(() => this.updateSigninStatus());` is preferable in TypeScript because the callback will be typechecked. – Aluan Haddad Apr 21 '17 at 07:50
  • 1
    @AluanHaddad yes of course sir but I don't know in which callback parameter `listen` method gives the `isSignedIn` parameter that the `updateSigninStatus` method uses so I wanted stay on the safe side. – eko Apr 21 '17 at 07:53
  • 1
    @echonax that is a fair point. I assume it must pass at least one potentially truthy value so actually I should have suggested `.listen(status => this.updateSigninStatus(status));` – Aluan Haddad Apr 21 '17 at 07:55
  • Thanks again. I tried that change as well and I don't see any difference. The last network call is the Google API discovery call. No error... ¯\_(ツ)_/¯ – beachCode Apr 21 '17 at 16:00
5

After messing around with this, I found that a better sample for my use case was this one: https://cloud.google.com/compute/docs/tutorials/javascript-guide

Note that I am using the first suggestion as well:

gapi.auth2.getAuthInstance().isSignedIn.listen(status => this.updateSigninStatus(status));

I was able to get everything working after I realized that I had to init gapi.auth with everything I wanted the first time--I thought I could just authorize again later with different scopes. I'm now doing it in index.html like this:

    var PROJECT_ID = 'projectname';
    var CLIENT_ID = 'xxxx.apps.googleusercontent.com';
    var API_KEY = '1234';
    var SCOPES = 'https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.readonly';

    /**
    * Authorize Google Compute Engine API.
    */
    function authorization() {
      gapi.client.setApiKey(API_KEY);
      gapi.auth.authorize({
        client_id: CLIENT_ID,
        scope: SCOPES,
        immediate: false
      }, function(authResult) {
          if (authResult && !authResult.error) {
            window.alert('Auth was successful!');
          } else {
            window.alert('Auth was not successful');
          }
        }
      );
     }
beachCode
  • 3,202
  • 8
  • 36
  • 69