停止 angular-ui-router 导航,直到承诺得到解决 [英] stop angular-ui-router navigation until promise is resolved

查看:23
本文介绍了停止 angular-ui-router 导航,直到承诺得到解决的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想防止发生 rails 设计超时时发生的一些闪烁,但 angular 直到资源的下一个授权错误才知道.

I want to prevent some flickering that happens when rails devise timeout occurs, but angular doesn't know until the next authorization error from a resource.

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

What happens is that the template is rendered, some ajax calls for resources happen and then we are redirected to rails devise to login. I would rather do a ping to rails on every state change and if rails session has expired then I will immediately redirect BEFORE the template is rendered.

ui-router 有解决方案,可以放在每条路线上,但看起来一点也不枯燥.

ui-router has resolve that can be put on every route but that doesn't seem DRY at all.

我拥有的是这个.但是在状态已经转换之前,promise 不会被解决.

What I have is this. But the promise is not resolved until the state is already transitioned.

$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 的结果中断状态转换?

How can I interrupt the state transition, before the new template is rendered, based on the result of a promise?

推荐答案

我知道这对游戏来说太晚了,但我想把我的意见放在那里并讨论我认为暂停"一个很好的方法状态变化.根据 angular-ui-router 的文档,作为承诺的状态的解析"对象的任何成员都必须在状态加载完成之前被解析.所以我的功能(虽然尚未清理和完善)解决方案是向$stateChangeStart"上的toState"的解析对象添加一个承诺:

I know this is extremely late to the game, but I wanted to throw my opinion out there and discuss what I believe is an excellent way to "pause" a state change. Per the documentation of angular-ui-router, any member of the "resolve" object of the state that is a promise must be resolved before the state is finished loading. So my functional (albeit not yet cleaned and perfected) solution, is to add a promise to the resolve object of the "toState" on "$stateChangeStart":

例如:

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

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

This will ensure that the state-change holds for the promise to be resolved which is done when the API call finishes and all the decisions based on the return from the API are made. I've used this to check login statuses on the server-side before allowing a new page to be navigated to. When the API call resolves I either use "event.preventDefault()" to stop the original navigation and then route to the login page (surrounding the whole block of code with an if state.name != "login") or allow the user to continue by simply resolving the deferred promise instead of trying to using bypass booleans and preventDefault().

虽然我确信原发帖者早就发现了他们的问题,但我真的希望这能帮助其他人.

Although I'm sure the original poster has long since figured out their issue, I really hope this helps someone else out there.

编辑

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

I figured I didn't want to mislead people. Here's what the code should look like if you are not sure if your states have resolve objects:

$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 中添加它:

in order to get this working for states that don't have a resolve definition you need to add this in the app.config:

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

            return $delegate.apply(this, arguments);
        };

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

doing if (!toState.resolve) { toState.resolve = {} }; in stateChangeStart doesn't seem to work, i think ui-router doesn't accept a resolve dict after it has been initialised.

这篇关于停止 angular-ui-router 导航,直到承诺得到解决的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆