如何在AngularJS或Javascript中实现类似于c# '

本文关键字:类似于 实现 AngularJS Javascript | 更新日期: 2023-09-27 18:15:35

我正在做一个项目,需要我让我的用户登录使用谷歌,我使用谷歌API客户端(参考可以在这里找到)。

现在我的代码是这样的

文件:服务/auth-service.js

angular.module('myApp')
  .factory('gapi', function ($q) {
    var auth2;
    gapi.load('auth2', function () {
      auth2 = gapi.auth2.init({
        client_id: '649922003965-ni9e6nad25dh3ejoll70va550kt7cu5u.apps.googleusercontent.com'
      });
    });
    return {
      isSignedIn: function () {
        return auth2.isSignedIn.get();
      }
    }
  });

文件:控制器/dashboard.js

angular.module('myApp')
  .controller('DashboardCtrl', function (gapi) {
      alert(gapi.isSignedIn());
  });

现在的问题是,当alert()命令在dashboard.js文件中运行时,到那时auth2还没有加载(因为它通过互联网从Google API加载我猜),因此我得到一个错误,isSignedIn不能被称为未定义。

所以我理想情况下需要的可能是类似c# await函数的东西,它等待返回的值,然后调用它的方法。任何解决方案都将非常感激。我花了几个小时尝试承诺和其他方法,但我没能让他们任何一个工作。

更新:你的大多数答案都适用于上面提到的场景。让我们来试试这个更复杂的场景,这个场景一开始就应该提到。(对不起)。

文件:脚本/app.js

.state('main', {
   url: '/admin',
   abstract: 'true',
   templateUrl: 'views/main.html',
   resolve: {
     check: function ($q, auth) {
       if(!auth.isSignedIn())
       {
          $q.reject({authenticated: 'false'});
       }
     }
   }
 })
 .state('admin', {
   url: '',
   parent: 'main',
   templateUrl: 'views/admin.html'
 })

现在,如果我在这里使用promise, angular就不会等待promise被解析。它将简单地加载视图并调用$q。

如何在AngularJS或Javascript中实现类似于c# '

您可以通过以下方式使用承诺来实现:

文件:服务/auth-service.js

angular.module('myApp')
  .factory('gapi', function ($q) {
    var auth2;
    var isSignedInDeferred = $q.defer();
    gapi.load('auth2', function () {
      auth2 = gapi.auth2.init({
        client_id: '649922003965-ni9e6nad25dh3ejoll70va550kt7cu5u.apps.googleusercontent.com'
      });
      isSignedInDeferred.resolve(auth2.isSignedIn.get());
    });
    return {
      isSignedIn: function () {
        return isSignedInDeferred.promise;
      }
    }
  });

文件:控制器/dashboard.js

angular.module('myApp')
  .controller('DashboardCtrl', function (gapi) {
      gapi.isSignedIn().then(isSigned) {
          alert(isSigned);
      }
  });

只要改变你的isSignedIn函数返回promise,并在你有值时解析该promise。

该特性在ES7的草案中可用,babel(一个转译器)支持async/await,如果你觉得舒服的话。话虽如此,这可以很容易地通过promise实现:

gapi.client.load(name, version, callback)

将客户端库接口加载到特定的API。如果是回调,则返回一个promise 。加载的API接口将以gapi.client.api.collection.method的形式出现。例如,Moderator API会创建这样的方法gapi.client.moderator.series.list .

api已经给了你一个承诺,所以没有必要把它包裹在q周围,你所需要做的就是返回那个承诺:

return gapi.load('auth2').then(function() {
    return gapi.auth2.init({
       client_id: '649922003965-ni9e6nad25dh3ejoll70va550kt7cu5u.apps.googleusercontent.com'
    });
});

现在,从你的控制器:

gapi.then(function(auth2){
  //auth2 already loaded
});

Edit:假设您可以在检查函数上获得返回的承诺。你只需要:

var possiblyRejectedPromise = gapi.then(function(auth2){
   if(!auth2.isSignedIn.get()){
       throw new Error('Not logged in');
   } else {
       //LoggedIn
       return true;
   }
 });
return possiblyRejectedPromise;

ES5中没有等价的await。你需要养成一种心态,即在事件发生时处理事件,并根据这些事件更新应用程序状态。

对于您的具体问题,我相信您的假设是正确的,因为auth2变量尚未设置(因此未定义),所以它失败了。"auth2 undefined"状态是代码需要处理的应用程序状态之一。解决方案可能很简单,只需像这样更改isSignedIn函数:

isSignedIn: function () {
    return auth2 && auth2.isSignedIn.get();
}

这样,只有当auth2变量被设置并且isSignedIn属性为true时,它才会返回true。