Skip to main content
 首页 » 编程设计

angularjs之停止 Angular-ui-router 导航,直到 promise 得到解决

2024年06月20日9telwanggs

我想防止发生 Rails 设计超时时发生的一些闪烁,但 Angular 直到资源出现下一个授权错误时才知道。

发生的情况是模板被渲染,一些ajax调用资源发生,然后我们被重定向到rails设备进行登录。我宁愿在每次状态更改时对 Rails 执行 ping 操作,如果 Rails session 已过期,那么我将在渲染模板之前立即重定向。

ui-router 具有可以放在每个路由上的解析,但这看起来一点也不干。

我有的是这个。但只有在状态发生转变之前,这一 promise 才得以实现。

$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){ 
        //check that user is logged in 
        $http.get('/api/ping').success(function(data){ 
          if (data.signed_in) { 
            $scope.signedIn = true; 
          } else { 
            window.location.href = '/rails/devise/login_path' 
          } 
        }) 
 
    }); 

在呈现新模板之前,如何根据 promise 的结果中断状态转换?

请您参考如下方法:

我知道这对于游戏来说已经太晚了,但我想发表我的意见并讨论我认为“暂停”状态更改的绝佳方法。根据 angular-ui-router 的文档,状态的“解析”对象的任何成员(作为 promise )必须在状态完成加载之前解析。所以我的功能(尽管尚未清理和完善)解决方案是在“$stateChangeStart”上向“toState”的解析对象添加一个 promise :

例如:

$rootScope.$on('$stateChangeStart', function (event, toState, toParams) { 
    toState.resolve.promise = [ 
        '$q', 
        function($q) { 
            var defer = $q.defer(); 
            $http.makeSomeAPICallOrWhatever().then(function (resp) { 
                if(resp = thisOrThat) { 
                    doSomeThingsHere(); 
                    defer.resolve(); 
                } else { 
                    doOtherThingsHere(); 
                    defer.resolve(); 
                } 
            }); 
            return defer.promise; 
        } 
    ] 
}); 

这将确保状态更改适用于要解决的 promise ,这是在 API 调用完成并且基于 API 返回做出所有决策时完成的。在允许导航到新页面之前,我使用它来检查服务器端的登录状态。当 API 调用解析时,我要么使用“event.preventDefault()”停止原始导航,然后路由到登录页面(用 if state.name != "login"包围整个代码块),或者允许用户通过简单地解决延迟的 promise 来继续,而不是尝试使用旁路 bool 值和 PreventDefault()。

虽然我确信原始发帖者早已解决了他们的问题,但我真的希望这对其他人有帮助。

编辑

我想我不想误导人们。如果您不确定您的状态是否有解析对象,则代码应如下所示:

$rootScope.$on('$stateChangeStart', function (event, toState, toParams) { 
    if (!toState.resolve) { toState.resolve = {} }; 
    toState.resolve.pauseStateChange = [ 
        '$q', 
        function($q) { 
            var defer = $q.defer(); 
            $http.makeSomeAPICallOrWhatever().then(function (resp) { 
                if(resp = thisOrThat) { 
                    doSomeThingsHere(); 
                    defer.resolve(); 
                } else { 
                    doOtherThingsHere(); 
                    defer.resolve(); 
                } 
            }); 
            return defer.promise; 
        } 
    ] 
}); 

编辑2

为了使其适用于没有解析定义的状态,您需要将其添加到 app.config 中:

   var $delegate = $stateProvider.state; 
        $stateProvider.state = function(name, definition) { 
            if (!definition.resolve) { 
                definition.resolve = {}; 
            } 
 
            return $delegate.apply(this, arguments); 
        }; 

在 stateChangeStart 中执行 if (!toState.resolve) { toState.resolve = {} }; 似乎不起作用,我认为 ui-router 在它之后不接受解析字典已初始化。