一点信息.我正在开发一个单页应用程序,但我试图使它只是一个
HTML文件,而不是包含其中所有引导程序信息的实际动态页面.我也希望,当应用程序启动时(或者可能在之前),检查当前会话是否“登录”,如果没有,则将哈希指向“登录”.
我是Angular的新手,我很难搞清楚如何编写这个流程.所以,实质上……
> HTML页面加载了“延迟”引导程序
>点击URL以获取登录状态
>如果状态为“未登录”,请直接转至#/ login
>启动应用
有关#2和#3住在哪里的任何指示?在我的“简单世界”中,我只是使用jquery来获取数据,然后调用angular.resumeBootstrap([appname]).但是,由于我正在尝试实际学习Angular,而不是仅仅修复我不理解的部分,我想知道在这个地方会使用什么.我在看供应商,但我不确定这是我需要的.
谢谢!
编辑
基于@ Mik378的答案,我已将我的代码更新为以下测试.它适用于某一点,但由于’get’是异步的,它允许应用程序继续加载之前的任何内容然后拍摄状态结果.
var app = angular.module('ping', [
'ngRoute',
'ping.controllers'
]).provider('security', function() {
this.$get = ['$http', function($http) {
var service = {
getLoginStatus: function () {
if (service.isAuthenticated())
return $q.when(service.currentUser);
else
return $http.get('/login/status').then(function (response) {
console.log(response);
service.loggedIn = response.data.loggedIn;
console.log(service);
return service.currentUser;
});
},
isAuthenticated: function () {
return !!service.loggedIn;
}
};
return service;
}];
}).run(['security', function(security) {
return security.getLoginStatus().then(function () {
if(!security.isAuthenticated()) {
console.log("BADNESS");
} else {
console.log("GOODNESS");
}
});
}]);
我希望这可以在第一个控制器启动之前以某种方式完成,这样它就不会加载(或试图加载)尚未被访问的东西.
编辑#2
我开始研究路由器中的’resolve’属性,@ Mik378验证了我在看什么.我的最终代码(当前)正如我所希望的那样如下(关于超长代码块的应用)
angular.module('ping.controllers', [])
.controller('Dashboard', ['$scope', function($scope) {
console.log('dashboard')
}])
.controller('Login', ['$scope', function($scope) {
console.log('login')
}]);
var app = angular.module('ping', [
'ngRoute',
'ping.controllers'
]).run(['$rootScope', '$location', function($root, $location) {
$root.$on("$routeChangeError", function (event, current, previous, rejection) {
switch(rejection) {
case "not logged in":
$location.path("/login"); //<-- NOTE #1
break;
}
});
}]);
app.provider('loginSecurity', function() {
this.$get = ['$http', '$q', function($http, $q) {
var service = {
defer: $q.defer, //<-- NOTE #2
requireAuth: function() { //<-- NOTE #3
var deferred = service.defer();
service.getLoginStatus().then(function() {
if (!service.isAuthenticated()) {
deferred.reject("not logged in")
} else {
deferred.resolve("Auth OK")
}
});
return deferred.promise;
},
getLoginStatus: function() {
if (service.isAuthenticated()) {
return $q.when(service.currentUser);
} else {
return $http.get('/login/status').then(function(response) {
console.log(response);
service.loggedIn = response.data.loggedIn;
console.log(service);
return service.currentUser;
});
}
},
isAuthenticated: function() {
return !!service.loggedIn;
}
};
return service;
}
];
});
app.config(['$routeProvider', function($routeProvider) {
console.log('Routing loading');
$routeProvider.when('/', {
templateUrl: 'static/scripts/dashboard/template.html',
controller: 'Dashboard',
resolve: {'loginSecurity': function (loginSecurity) {
return loginSecurity.requireAuth(); //<- NOTE #4
}}
});
$routeProvider.when('/login', {
templateUrl: 'static/scripts/login/template.html',
controller: 'Login'
});
$routeProvider.otherwise({redirectTo: '/404'});
}]);
笔记:
>此部分涉及路由故障.在“无法登录”的情况下,我想抓住失败并将人员弹出到登录页面.
>我无法访问requireAuth函数中的$q,所以我抓住了它的引用.这可能是一种更好的方法吗?
>这个函数包装了另外两个 – 它使用从getLoginStatus返回的promise,但返回它自己的promise,如果getLoginStatus的最终结果在用户没有登录的情况下结束,它将被拒绝.这样做.
>这将返回#3的承诺,$routeProvider使用它.所以如果失败,路由失败,你最终会在#1处捕获它.
呼.我认为这一天就足够了.是时候喝啤酒了.
最佳答案 无需为您的案例使用延迟引导程序:
angular.module('app').run(['security', '$location', function(security) {
// Get the current user when the application starts
// (in case they are still logged in from a previous session)
security.requestCurrentUser().then(function(){
if(!security.isAuthenticated())
$location.path('yourPathToLoginPage')
}; //service returning the current user, if already logged in
}]);
此方法requestCurrentUser将如下:
requestCurrentUser: function () {
if (service.isAuthenticated())
return $q.when(service.currentUser);
else
return $http.get('/api/current-user').then(function (response) {
service.currentUser = response.data.user;
return service.currentUser;
});
}
和内部安全服务再次:
isAuthenticated: function () {
return !!service.currentUser;
}
注意模块的运行方法=>应用程序运行后,将立即调用此服务.
– 更新 –
为了防止在requestCurrentUser提供的promise之前初始化任何控制器,在下面的注释中提到的更好的解决方案是使用resolve route属性.