如何获知 ui-router 中的状态更改取消?

How to be informed of state change cancellations in ui-router?

所以我在我的应用程序中使用 UI-router,我使用 $stateChangeStart 侦听器来显示加载程序,然后使用 $stateChangeSuccess 隐藏加载程序。这样我在状态转换之间就有了一个加载器。

$rootScope.$on('$stateChangeStart',
                function (event, toState, toParams, fromState, fromParams) {
///show loader
});

$rootScope.$on('$stateChangeSuccess',
                function (event, toState, toParams, fromState, fromParams) {
//hide loader
});

问题:

  1. 我处于状态 A
  2. 我点击一个按钮进入状态B,$stateChangeStart为B调用,显示我的加载程序。
  3. 我立即点击另一个按钮进入状态 A(B 有一些东西需要解决,所以在 B 的 UI 实际开始加载之前还有时间)
  4. B 未加载,$stateChangeSuccess 未被调用,我的加载器从未被隐藏(因为我们已经在 A 中,所以不会重新加载)

那么有什么方法可以监听状态更改取消并隐藏我的加载器吗?

更新: 我创建了一个 Plunk。在 plunk 中,我在 B 的 resolve 中设置了 10 秒的超时。所以在它解决之前,点击 A。监视状态更改侦听器事件的控制台。

2015 年 7 月 25 日更新,使用最新的 AngularUI 路由器: 创建了新 Plunk

到目前为止,我发现的唯一可持续解决方案是避免使用 ui-sref。它屏蔽了 $state.go 的 return 值,这在本例中是关键。

诀窍是处理由 $state.go

编辑的 transition 承诺 return
$scope.safeGo = function(stateName){
  var transition = $state.go(stateName);
  transition.then(function(currentState){
    console.log('Transition finished successfully. State is ' + currentState.name);
  })
  .catch(function(err){
    //revert your loader animation here
    console.log('Transition failed. State is ' + $state.current.name, err);
  })
}

可以通过 $state.transition 属性 访问同一对象,但是在转换之间 属性 是 null 并且在 $state 广播的任何事件中它也是 null。因此,唯一可靠的选择是获取 $state.go.

的 return 值

如果在 B 解决之前选择了状态 ABtransition 承诺将被拒绝,原因是 Error: transition superseded。但是,您仍然需要等到 B.resolve 完成。如果你想避免这种情况,你将不得不自己跟踪你的状态,因为到 A 的转换将立即得到解决(因为当前状态仍然是 AB 正在尝试解决)。

已更新plunker