承诺后的角度状态变化

Angular state change after a promise

本文关键字:状态 变化 承诺      更新时间:2023-09-26

我不确定这是否重复,但我没有找到任何对我有用的东西,所以我发布了这个问题。

在将用户引导到特定路线之前,我需要从数据库中获取值,这样我就可以决定显示什么内容。

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

有没有一种方法可以在状态更改开始时防止默认,并在状态更改结束时重定向用户?此外,如果我们可以在状态更改开始时防止默认,那么我们如何继续默认状态?

(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
                })
        }
    }]);
});

您可以在$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的文档可在处获得

请注意,如果不需要支持IE ,可以使用Promise对象而不是$q服务

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

.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);
            }
        }
    })

然后按照以下处理消息"notValid"

.run(function($state,$rootScope){
        $rootScope.$on("notValid",function(event,message){
        $state.transitionTo('whereever');
    });
})