javascript – 在Angular中,如何在启动之前从服务器获取引导数据?

一点信息.我正在开发一个单页应用程序,但我试图使它只是一个
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属性.

点赞