web-dev-qa-db-ja.com

Angular-UI-Router Resolveのエラーを処理する方法

ステートに移行する前に、angular-ui-routerのresolveを使用してサーバーからデータを取得しています。サーバーへのリクエストが失敗する場合があり、ユーザーに失敗について通知する必要があります。コントローラーからサーバーを呼び出す場合、thenを入れて、呼び出しが失敗した場合に通知サービスを呼び出すことができます。サーバーへの呼び出しをresolveに入れました。これは、子孫の状態がサーバーからの結果を開始前に待機するようにするためです。

サーバーへの呼び出しが失敗した場合、どこでエラーをキャッチできますか? (私は documentation を読みましたが、それでも方法はわかりません。また、この新しいスニペットツールを試してみる理由を探しています:)。

"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>
43
Endy Tjahjono

問題は、ルート解決の依存関係のいずれかが拒否された場合、コントローラー notインスタンス化されます。そのため、インスタンス化されたコントローラーで検出できるデータに障害を変換できます。

擬似コードの例:-

   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 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
        }]
      },
"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="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>
22
PSL

古い質問ですが、私は同じ問題を抱えていて、ui-routerのFAQセクションでこれにつまずいた

状態の解決関数内で発生したために些細なエラーが捕捉されないという問題がある場合、これは実際には仕様ごとのPromiseの意図された動作です。

解決内のエラー

このように、アプリの実行段階ですべての解決エラーをキャッチできます

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