Подтвердить что ты не робот

Как обрабатывать ошибку в решении angular -ui-router

Я использую 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
        };
      }]
    });
  }
]);
<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>
4b9b3361

Ответ 1

Проблема заключается в том, что если какая-либо из зависимостей в решении маршрута отклоняется, контроллер не будет быть создан. Таким образом, вы можете преобразовать отказ в данные, которые вы можете обнаружить в создаваемом контроллере.

Пример Псевдокод: -

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

и в вашем контроллере: -

 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
        };

Если вы совершаете вызов $http или похожий, вы можете использовать http обещают, чтобы разрешать данные всегда даже в случае сбоя и возвращать статус контроллеру.

Пример: -

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
        }]
      },

"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"
        };
        
      }]
    });
  }
]);
 <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
    <script data-require="[email protected]*" 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>

Ответ 2

Старый вопрос, но у меня была такая же проблема и наткнулся на это в разделе FAQ по ui-router

Если у вас возникли проблемы, когда не было обнаружено тривиальной ошибки потому что это происходило в пределах функции разрешения состояния, это на самом деле является предполагаемым поведением promises за спецификацию.

ошибки в решении.

Таким образом, вы можете уловить все ошибки разрешения на этапе запуска вашего приложения, например

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