如何处理angular-ui-router的解决方案中的错误

End*_*ono 43 angularjs angular-ui-router angular-promise

我正在使用angular-ui-router resolve来从服务器获取数据,然后再转到状态.有时,对服务器的请求失败,我需要通知用户有关失败的信息.如果我从控制器调用服务器,我可以在then其中调用我的通知服务,以防呼叫失败.我将调用放入服务器,resolve因为我希望后代状态在服务器启动之前等待服务器的结果.

如果对服务器的调用失败,我在哪里可以捕获错误?(我已经阅读了文档,但仍然不确定如何.另外,我正在寻找尝试这个新代码段工具的理由:).

"use strict";

angular.module('MyApp', ["ui.router"]).config([
  "$stateProvider",
  "$urlRouterProvider",
  function ($stateProvider, $urlRouterProvider) {
    $urlRouterProvider.otherwise("/item");
    $stateProvider
    .state("list", {
      url: "/item",
      template: '<div>{{listvm}}</div>' +
      	'<a ui-sref="list.detail({id:8})">go to child state and trigger resolve</a>' +
        '<ui-view />',
      controller: ["$scope", "$state", function($scope, $state){
          $scope.listvm = { state: $state.current.name };
      }]
    })
    .state("list.detail", {
      url: "/{id}",
      template: '<div>{{detailvm}}</div>',
      resolve: {
        data: ["$q", "$timeout", function ($q, $timeout) {
          var deferred = $q.defer();
          $timeout(function () {
            //deferred.resolve("successful");
            deferred.reject("fail");   // resolve fails here
          }, 2000);
          return deferred.promise;
        }]
      },
      controller: ["$scope", "data", "$state", function ($scope, data, $state) {
        $scope.detailvm = {
          state: $state.current.name,
          data: data
        };
      }]
    });
  }
]);
Run Code Online (Sandbox Code Playgroud)
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.10/angular-ui-router.min.js"></script>

<div ng-app="MyApp">
  <ui-view />
</div>
Run Code Online (Sandbox Code Playgroud)

koo*_*x00 78

老问题,但我遇到了同样的问题,并在ui-router的FAQ部分发现了这个问题

如果您遇到的问题是由于在一个州的解析函数中发生了一个微不足道的错误,这实际上是每个规范的承诺的预期行为.

解决中的错误.

因此,您可以像这样在应用程序的运行阶段捕获所有解决错误

$rootScope.$on('$stateChangeError', 
function(event, toState, toParams, fromState, fromParams, error){ 
        // this is required if you want to prevent the $UrlRouter reverting the URL to the previous valid location
        event.preventDefault();
        ... 
})
Run Code Online (Sandbox Code Playgroud)

  • 这应该是公认的答案.imho使用`resolve`的全部意义是不必处理控制器中的数据! (23认同)

PSL*_*PSL 22

问题是如果拒绝路由解析中的任何依赖项,则不会实例化控制器.因此,您可以将故障转换为可在实例化控制器中检测到的数据.

示例伪码: -

   data: ["$q", "$timeout","$http", function ($q, $timeout, $http) {
      return $timeout(function () { //timeout already returns a promise
        //return "Yes";
        //return success of failure
         return success ? {status:true, data:data} : {status:false}; //return a status from here
       }, 2000);
     }]
Run Code Online (Sandbox Code Playgroud)

在你的控制器中: -

 controller: ["$scope", "data", "$state", function ($scope, data, $state) {
      //If it has failed
      if(!data.status){
        $scope.error = "Some error";
       return;
      }
        $scope.detailvm = {
          state: $state.current.name,
          data: data
        };
Run Code Online (Sandbox Code Playgroud)

如果您正在进行$http呼叫或类似呼叫,即使发生故障也可以使用http promise来解析数据,并将状态返回给控制器.

例:-

resolve: {
        data: ["$q", "$timeout","$http", function ($q, $timeout, $http) {
           return $http.get("someurl")
             .then(function(){ return {status:true , data: "Yes"} }, 
                    function(){ return {status:false} }); //In case of failure catch it and return a valid data inorder for the controller to get instantated
        }]
      },
Run Code Online (Sandbox Code Playgroud)

"use strict";

angular.module('MyApp', ["ui.router"]).config([
  "$stateProvider",
  "$urlRouterProvider",
  function ($stateProvider, $urlRouterProvider) {
    $urlRouterProvider.otherwise("/item");
    $stateProvider
    .state("list", {
      url: "/item",
      template: '<div>{{error}}</div><div>{{listvm}}</div>' +
      	'<a ui-sref="list.detail({id:8})">go to child state and trigger resolve</a>' +
        '<ui-view />',
      controller: ["$scope", "$state", function($scope, $state){
       $scope.listvm = { state: $state.current.name };
      }]
    })
    .state("list.detail", {
      url: "/{id}",
      template: '<div>{{detailvm}}</div>',
      resolve: {
        data: ["$q", "$timeout","$http", function ($q, $timeout, $http) {
           return $http.get("/").then(function(){ return {status:true , data: "Yes"} }, function(){ return {status:false} })
        }]
      },
      controller: ["$scope", "data", "$state", function ($scope, data, $state) {
   
    
        $scope.detailvm = {
          state: $state.current.name,
          data: data.status ? data :"OOPS Error"
        };
        
      }]
    });
  }
]);
Run Code Online (Sandbox Code Playgroud)
 <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
    <script data-require="angular-ui-router@*" data-semver="0.2.10" src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.10/angular-ui-router.js"></script>
  <div ng-app="MyApp">
      <ui-view></ui-view>
    </div>
Run Code Online (Sandbox Code Playgroud)

  • 这样你就必须在每个控制器中实现错误处理,对吧?我更喜欢你监听由ui路由器广播的错误事件的方法并对其做出响应,因为在这种情况下错误处理是集中的. (4认同)