解决路由解析属性中的承诺

时间:2016-08-05 14:45:13

标签: angularjs

是否可以在路由器的resolve属性中使用promises? 我想使用服务检查用户是否有权访问路由解析中的页面。 例如:

         $stateProvider
            .state('user', {
                url: '/user',
                templateUrl: 'app/views/user/views/user.html',
                controller: 'UserCtrl',
                controllerAs: 'vm',
                resolve: {
                    security: ['$state', 'userService','messageService','$location', function ($state, userService, messageService, $location) {
                        userService.checkUserAndRole("user").then(function(data){
                        var data = userService.checkUserAndRole("user");
                        if (data.access === false) {
                            messageService.errorMsg(data.message);
                            var route = data.route ? data.route:$location.path();
                            $state.go(route);
                        });
                    }]
                }
            });

我在userService中使用$ q服务来返回一个承诺

    function checkUserAndRole(page){
        var defer = $q.defer();
        var response = {};
        if(!ROLE[page]){
            response.access = false;
            response.message = "Page is not defined in ROLE config. Please tell admin to correct this!";
            response.route = "login";
            defer.resolve(response);
        }

        if(!user.roles){
            response.access = false;
            response.message = "Logged in user does not seem to have any role data defined. That is why you are redirected";
            response.route = "/";
            defer.resolve(response);
        }

        if(!helperService.arrayIntersect(ROLE[page],user.roles)){
            response.access = false;
            response.message = "You don't have a permission to access '/"+page+"' url";
            defer.resolve(response);
        }

        response.access = true;
        response.message = "";
        response.route = "";

        return defer.promise;
    }

如果我不使用promises但是立即从服务中返回数据一切正常但是在刷新时我仍然得到无效结果,因为来自服务的用户数据是通过$ http获取的,并且当路由是解决。

1 个答案:

答案 0 :(得分:1)

解决功能与promises一起使用,但返回对解析器功能的承诺非常重要。

$stateProvider
    .state('user', {
        url: '/user',
        templateUrl: 'app/views/user/views/user.html',
        controller: 'UserCtrl',
        controllerAs: 'vm',
        resolve: {
            security: ['$state', 'userService','messageService','$location', function ($state, userService, messageService, $location) {
                //RETURN the promise
                return (
                    userService.checkUserAndRole("user")
                        .then(function(data){
                            if (data.access === false) {
                                messageService.errorMsg(data.message);
                                var route = data.route ? data.route:$location.path();
                                $state.go(route);
                        });
                );
            }]

        }
    });

由于未能返回对解析程序功能的承诺,路由器会将security解析为null,而不会等待承诺完成。

如果checkUserAndRole条件都不成立,$q.defer函数也无法解析if。代码需要重写。

function checkUserAndRole(page){
    var response = {};
    var promise = $q.when();
    if(!ROLE[page]){
        response.access = false;
        response.message = "Page is not defined in ROLE config. Please tell admin to correct this!";
        response.route = "login";
        promise = $q.when(response);
    } else if(!user.roles) {
        response.access = false;
        response.message = "Logged in user does not seem to have any role data defined. That is why you are redirected";
        response.route = "/";
        promise = $q.when(response);
    } else if(!helperService.arrayIntersect(ROLE[page],user.roles)){
        response.access = false;
        response.message = "You don't have a permission to access '/"+page+"' url";
        promise = $q.when(response);
    } else {
        response.access = true;
        response.message = "";
        response.route = "";
        promise = $q.when(response);
    };

    return promise;
}

避免$q.defer,因为它容易出现编码错误。而是使用$q.when从值创建承诺。