Trouble signing out with Google Sign in (gapi) with angularjs

时光毁灭记忆、已成空白 提交于 2020-01-04 03:13:32

问题


So I have tried the following templates trying to integrate this:

HTML:

<google-sign-in-button button-id="login-button" options="options"></google-sign-in-button>

CSS:

.directive('googleSignInButton', function() {
    return {
      scope: { buttonId: '@', options: '&' }, 
      template: '<div></div>',
      link: function(scope, element, attrs) { 
        var div = element.find('div')[0]; 
        div.id = attrs.buttonId; 
        gapi.signin2.render(div.id, scope.options());
       }
    };
})

--

I've also just tried doing this in the header and using the regular sign in button:

HTML:

<div class="g-signin2" data-onsuccess="onSignIn"></div>

IN THE HEADER:

<script>
    window.onLoadCallback = function(){
      gapi.auth2.init({
          client_id: '123.apps.googleusercontent.com'
        });
    }
</script>

No matter what I do, i can't figure out how to log a user out. In my controller, when i try and do gapi.auth.signOut(); it says gapi is undefined

EDIT:

I've also tried dabbling in this to log a person out on run but ideally i'd want to make a log out work anywhere and not just when the page loads. I just don't really know where to put it or the correct way to make it happen:

.run(function ($rootScope, $state) {
    gapi.load('auth2', function() {
        auth2 = gapi.auth2.init();
        auth2.then(function(){
            auth2.signOut();
        });
    });
})

EDIT #2:

I also tried to create this factory with a resolve on my ui-router but it's not getting the data in time or at all

.factory('Auth', function($http, $state, $q, $rootScope) {
    var factory = { loggedIn: loggedIn };
    return factory;

    function loggedIn() {
        gapi.load('auth2', function() {
            auth2 = gapi.auth2.init();
            auth2.then(function(){
                return auth2.isSignedIn.get();
            });
        });
    }

})

EDIT #3:

I tried creating a service but I keep getting the following error for some reason to even test it:

Error: undefined is not an object (evaluating 'gapi.auth2.init')

.service('googleService', ['$http', '$rootScope', '$q', function ($http, $rootScope, $q) {

    var self = this;

    this.signedIn = function() {
        auth2 = gapi.auth2.init();
        auth2.then(function(){
            return auth2.isSignedIn.get();
        });
    }

    this.signOut = function(){
        var auth2 = gapi.auth2.getAuthInstance();
        auth2.signOut().then(function () {
            console.log('User signed out.');
        });
    }

}])

.controller('login', ['$rootScope', '$scope', '$q', 'googleService', function ($rootScope, $scope, $q, googleService) {
    console.log(googleService.signedIn());

}])

回答1:


I build upon my fiddle from my previous answer on a related question. Basically what I added was a function to the controller scope that would be called when a user clicks on the signout button.

angular.module('app', [])
  .controller('MainController', ['$scope',
    function($scope) {
      $scope.isSignedIn = false;
      ...
      $scope.signOut = function(){
        var auth2 = gapi.auth2.getAuthInstance();
        auth2.signOut().then(function () {
          $scope.$apply(function(){
            $scope.isSignedIn = false;
            console.log('User signed out.');
          });
        });
      }
    }
  ])

I used the code snippet provided by Google documentation and that seemed to work immediately.
Do pay attention when changing variables in scope, you have to wrap your scope changes in $scope.$apply for angular to force to check changes in scope.

You can find the full code in this fiddle.
(I will be removing this Google api project at some point, so replace the API Key with your own if it doesn't work)

This is demo code, so if you would actually put this in project, I'd recommend hiding some of the complexity behind services and directives.


Update: if you want to use a service, you'll have to use angulars promises heavily, see $q docs.

Here's a sample on how you could create a service using promises and callbacks. There's no simple way to get around the callback hell. But I hope wrapping these things into a service will solve that partially.

Here's an updated fiddle taking advantage of the service. This is the js code:

angular.module('app', [])
  .controller('MainController', ['$scope','googleService',
    function($scope, googleService) {
      $scope.isSignedIn = false;
      googleService.load().then(function(){
        $scope.signIn = function(){
          googleService.signIn().then(function(){
            $scope.isSignedIn = googleService.isSignedIn();
          });
        };

        $scope.signOut = function(){
          googleService.signOut().then(function(){
            $scope.isSignedIn = googleService.isSignedIn();
          });
        };
      });
    }
  ])
  .service('googleService', ['$q', function ($q) {
    var self = this;
    this.load = function(){
      var deferred = $q.defer();
      gapi.load('auth2', function(){
        var auth2 = gapi.auth2.init();
        //normally I'd just pass resolve and reject, but page keeps crashing (probably gapi bug)
        auth2.then(function(){
          deferred.resolve();
        });
        addAuth2Functions(auth2);
      });
      return deferred.promise;
    };

    function addAuth2Functions(auth2){
      self.signIn = function() {
        var deferred = $q.defer();
        auth2.signIn().then(deferred.resolve, deferred.reject);
        return deferred.promise;
      };

      self.isSignedIn = function(){
        return auth2.isSignedIn.get();
      }

      self.signOut = function(){
        var deferred = $q.defer();
        auth2.signOut().then(deferred.resolve, deferred.reject);
        return deferred.promise;
      };
    }

}]);

Basically, inside the load function you wrap the complexity of loading gapi, and auth2. After the load promise resolved in your controller, you are certain that the signIn, signOut, etc will work because it is loaded.




回答2:


I took a slightly different approach. Though, I am not good enough to explain why your code does not work and this works for me. Hopefully, someone else can help on this.

Here is my approach. Let me know if this helps.

login.html

<script>var gapiOnLoadCallback = function() { window.gapiOnLoadCallback(); }</script>
<script src="https://apis.google.com/js/platform.js?onload=gapiOnLoadCallback" async defer></script>

<div id="googleLoginButton"></div>

<button ng-show="signedIn" ng-click="signOut()">Sign Out</button>

login.js

angular.module('app', [])
.controller('LoginController', ['$window','$scope', function($window, $scope) {

  $window.gapiOnLoadCallback = function() {

    gapi.signin2.render('googleLoginButton', {
      'onsuccess': onSuccess,
      'onfailure': onFailure
    });
  }

  var onSuccess = function(googleUser) {
    // Success handling here
  };

  var onFailure = function() {
    // Failure handling here
  };

  $scope.signOut = function() {
    var auth2 = gapi.auth2.getAuthInstance();
    auth2.signOut().then(function () {
      // Some UI update
    });
  };
};

login-directive.js

angular.module('app', []).directive("loginButton", function() {
  return {
    restrict: 'E',
    scope: {},
    templateUrl: 'login/login.html',
    controller: 'LoginController'
  }
});


来源:https://stackoverflow.com/questions/41682721/trouble-signing-out-with-google-sign-in-gapi-with-angularjs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!