如何在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。
您可以通过以下方式使用承诺来实现:
文件:服务/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。