承诺后的角度状态变化

时间:2016-07-19 08:46:48

标签: javascript angularjs angular-ui-router

我不确定这是否重复,但我没有设法找到适合我的任何内容,所以我发布了这个问题。

我有一种情况,我需要在将用户引导到某些路线之前从数据库中获取值,因此我可以决定显示哪些内容。

如果我在e.preventDefault()之前移动$state.go(..),那么它可行,但不正确。问题是它开始加载默认状态,当它从http获得响应时,它才会重定向到main.home。所以,让我们说,如果db请求需要2秒钟,那么在重定向到main.home之前需要2秒,这意味着用户在大约2秒内看到了它不应该看到的内容。 / p>

有没有办法在状态更改开始时阻止默认并在状态更改结束时重定向用户? 另外,如果我们可以在状态更改开始时阻止默认,那么我们怎样才能继续默认状态?

(function(){
    "use strict";
    angular.module('app.routes').run(['$rootScope', '$state', '$http', function($rootScope, $state, $http){
        /* State change start */
        $rootScope.$on('$stateChangeStart', function(e, to, toParams, from, fromParams){
            e.preventDefault();
            $http
                .get('/url')
                .error(function(err){
                    console.log(err);
                })
                .then(function(response){
                    if( response.data === 2 ){
                       // e.preventDefault()
                       $state.go('main.home');
                    }
                    // direct to default state
                })
        }
    }]);
});

2 个答案:

答案 0 :(得分:1)

您可以在$ stateProviderConfig中添加resolve部分。

在解决方案中,您可以向数据库发出请求并检查所需条件。如果您不希望用户访问此页面,您可以使用$ state.go()将其重定向到其他位置。

示例配置:

.state({
    name: 'main.home',
    template: 'index.html',
    resolve: {
        accessGranted: ['$http', '$state', '$q',
            function($http, $state, $q) {
                let deffered = $q.defer();
                $http({
                    method: 'GET',
                    url: '/url'
                }).then(function(data) {
                    if (data === 2) {
                        // ok to pass the user
                        deffered.resolve(true);
                    } else {
                        //no access, redirect
                        $state.go('main.unauthorized');
                    }
                }, function(data) {
                    console.log(data);
                    //connection error, redirect
                    $state.go('main.unauthorized');
                });
                return deffered.promise;
            }
        ]
    }
});

resolve的文档可用here

请注意,如果您不需要支持IE

,则可以使用Promise对象代替$ q服务

答案 1 :(得分:0)

处理这种情况的一种方法是添加拦截器,如下所示。

[assembly: Dependency (typeof (SaveAndLoad))]
namespace WorkingWithFiles {
    public class SaveAndLoad : ISaveAndLoad {
        public void SaveText (string filename, string text) {
            var documentsPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
            var filePath = Path.Combine (documentsPath, filename);
            System.IO.File.WriteAllText (filePath, text);
        }
        public string LoadText (string filename) {
            var documentsPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
            var filePath = Path.Combine (documentsPath, filename);
            return System.IO.File.ReadAllText (filePath);
        }
    }
}

然后处理消息' notValid'如下

.config(function ($httpProvider) {
        $httpProvider.interceptors.push('stateChangeInterceptor');
    }).factory('stateChangeInterceptor', function ($q, $window,$rootScope) {
        return  {
            'response': function(response) { 
                var isValid = true;//Write your logic here to validate the user/action. 
                /*
                * Here you need to allow all the template urls and ajax urls which doesn't 
                */
                if(isValid){
                   return response;
                }
                else{
                  $rootScope.$broadcast("notValid",{statusCode : 'INVALID'});
                }

            },
            'responseError': function(rejection) {
              return $q.reject(rejection);
            }
        }
    })