You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AngularJS基于Promise控制路由显隐时刷新出现404错误求助

问题成因

你遇到的404问题本质是AngularJS路由的注册时机问题:
$stateProvider的路由注册属于框架启动的配置阶段同步行为,你把路由注册逻辑包裹在异步fetch的结果判断里,刷新页面时AngularJS路由初始化会先执行,此时异步请求还没返回结果,maintenance.correspondence路由还没注册,路由系统匹配不到对应路径就会直接抛出404。而你从其他页面导航过来时异步请求已经返回、路由已经完成注册,所以表现正常。

解决方案

不要用异步结果控制路由是否注册,改为正常注册路由,把权限校验逻辑放到路由的resolve配置中实现:
resolve会在路由进入前执行你传入的逻辑,返回promise,只有promise被resolve时才会正常进入路由,否则会中断路由跳转。

代码实现

// 始终注册路由,不要加外层toggle条件判断
$stateProvider.state('maintenance.correspondence', {
    url: '/correspondence',
    data: {
        title: 'Correspondence',
        header: {
            heading: 'Correspondence',
            subheading: 'Correspondence'
        }
    },
    template: '<correspondence></correspondence>',
    controller: ($scope: IScope) => {
    },
    onExit: (BreadCrumbs: BreadCrumbs) => {
        BreadCrumbs.reset();
    },
    onEnter: (BreadCrumbs: BreadCrumbs, $stateParams: IStateParamsService) => {
        BreadCrumbs.add("Correspondence", "Correspondence", null, "maintenance.correspondence");
    },
    // 新增resolve块做开关校验
    resolve: {
        pageAccess: ($q, $state) => {
            return fetch("/pageToggle")
                .then(response => response.json())
                .then(response => {
                    const toggle = parseInt(response) === 1;
                    if (toggle) {
                        // 开关打开,正常放行
                        return true;
                    }
                    // 开关关闭,跳转404页,替换为你项目实际的404路由名
                    $state.go('404');
                    return $q.reject('无页面访问权限');
                })
                .catch(() => {
                    $state.go('404');
                    return $q.reject('开关接口请求失败');
                });
        }
    }
});

优化建议

AngularJS项目优先使用内置的$http服务发起请求,不需要手动封装$q,也不会出现数据变更后视图不同步的问题,改造后resolve逻辑如下:

resolve: {
    pageAccess: ($http, $q, $state) => {
        return $http.get('/pageToggle')
            .then(response => {
                const toggle = parseInt(response.data) === 1;
                if (!toggle) {
                    $state.go('404');
                    return $q.reject('无页面访问权限');
                }
                return true;
            })
            .catch(() => {
                $state.go('404');
                return $q.reject('开关接口请求失败');
            });
    }
}

导航入口隐藏处理

如果你需要在侧边栏、导航栏隐藏该路由的入口,可以把接口返回的开关状态存在全局权限服务或者$rootScope中,在导航对应的DOM节点上加ng-if="toggle"判断即可,不需要控制路由注册逻辑。


内容的提问来源于stack exchange,提问作者Raja R

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 18:24:08