2013-06-07 18 views
13

リクエストが完了した場合にのみ、を$routeProviderに入れて新しいルートを表示しようとしています。要求が成功すると、$ http.post()の結果が確定し、ビューがレンダリングされます。しかし、要求が失敗した場合(タイムアウトや内部エラーなど)、約束は決して解決されず、ビューはレンダリングされません。 resolveを使用してリクエストの失敗を処理するにはどうすればよいですか?

コードの最も重要な部分は怒鳴るです:

app.js

$routeProvider.when('/warrantyResult', { 
    templateUrl : 'partials/warranty-result.html', 
    controller : 'WarrantyResultCtrl', 
    resolve : { 
     response : [ 'Warranty', function(Warranty) { 
      return Warranty.sendRequest(); 
     } ] 
    } 
}); 

controllers.js

angular.module('adocDemo.controllers', []).controller('HomeCtrl', [ '$scope', function($scope) { 

} ]).controller('WarrantyCtrl', [ '$scope', '$http', '$location', 'Warranty', function($scope, $http, $location, Warranty) { 
    $scope.submitWarranty = function() { 
     $scope.loading = true; 
     Warranty.setRequestData($scope.data); 
     $location.path('/warrantyResult'); 
    }; 
} ]).controller('WarrantyResultCtrl', [ '$scope', 'Warranty', function($scope, Warranty) { 

    $scope.request = Warranty.getRequestData(); 
    $scope.response = Warranty.getResponseData(); 
} ]); 

services.js

angular.module('adocDemo.services', []).factory('Warranty', [ '$http', '$timeout', function($http, $timeout) { 
    /** 
    * This service is used to query the Warranty Webmethod. The sendRequest 
    * method is automaticcaly called when the user is redirected to 
    * /warrantyResult route. 
    */ 
    var isDataSet = false; 
    var requestData = undefined; 
    var responseData = undefined; 
    return { 
     setRequestData : function(data) { 
      //Setting the data 
      isDataSet = true; 
     }, 
     getRequestData : function() { 
      return requestData; 
     }, 
     sendRequest : function(data) { 
      if(isDataSet) { 
       var request = $http.post('url/to/webservice', requestData); 
       request.success(function(data) { 
        responseData = data; 
       }); 
       return request; 
      } 
     }, 
     getResponseData : function() { 
      return responseData; 
     } 
    }; 
} ]); 

私が知っています私は約束を使用することができます$ httpの呼び出しをラウンドし、要求が失敗であってもそれを解決しますが、単純な解決方法があるのだろうかと思います。うまくいけば

読んでくれてありがとうと、深い検索後:)

+0

解決に失敗したときのアプリの振る舞いに依存しますか? – Stewie

+0

解決が失敗したときに、ユーザーを別のルート(/ requestError?)にリダイレクトするのが最善の動作です。または、/ warrantyResultをレンダリングして、このルートのコントローラが要求が成功したかどうかをチェックすることができます。 – pdegand59

答えて

0

を助け、私はこの問題の解決策を見つけることができませんでした。

解決策のステートメントを自分のルート定義に入れることにしました。WarrantyCtrlに次のコードスニペットを使用しました。誰かがまだ元の問題の解決策を持っている場合は

$scope.submitWarranty = function() { 
    $scope.formatUserData(); 
    if ($scope.verifyUserData()) { 
     $scope.loading = true; 
     Warranty.setRequestData($scope.data); 
     Warranty.sendRequest().success(function() { 
      $location.path('/warrantyResult'); 
     }).error(function() { 
      $location.path('/webserviceError'); 
     }); 
    } 
}; 

非常に巧妙ないが、intentedとして働いて...、私はそれを読むことは非常に喜んでいただけることでしょう!

+0

'$ location.path( '/ webserviceError')'のみを持ち、 '$ http'呼び出しのエラーハンドラで実行してください。あなたがルート解決を持つことができるように、それはサービスで処理されるため、拒否された約束について考える必要はありません –

8

私はresolveからそれを行うための唯一の方法は、手動でWarranty.sendRequestによって返された約束を解決し、新しい約束でそれを再ラップすることだと思う:あなたはエラーが発生したかどうかを確認して生成することができ、WarrantyResultCtrl

resolve : { 
    response : [ 'Warranty' '$q', function(Warranty, $q) { 
    var dfd = $q.defer(); 

    Warranty.sendRequest().then(function(result) { 
     dfd.resolve({ success: true, result : result }); 
    }, function(error) { 
     dfd.resolve({ success : false, reason : error }); 
    }); 

    return dfd.promise; 

    } ] 
} 

リダイレクト。

EDIT:非常にクリーンなソリューション:

// WarrantyCtrl 
$scope.$on('$routeChangeError', function() { 
    // handle the error 
}); 
$scope.submitWarranty = function() { 
    $scope.loading = true; 
    Warranty.setRequestData($scope.data); 
    $location.path('/warrantyResult'); 
}; 

plunker demo

+0

あなたのプランナーが機能していません。しかし、あなたの答えはとにかく!私はあなたの解決策を打つつもりです。 – pdegand59

+0

@ pdegand59おっと、申し訳ありません!私は明らかにあまりにも多くの昨日をきれいにきれいにした:( – robertklep

3

私は何を発見したことはPromiserejected、そしてあなたのビューである場合、コントローラが全く解雇されていないということですあなたと同じようにレンダリングされることはありません。

私は何も発見することは、あなたの$routeProviderresolve.then()Promiseを扱う場合、.then()resolvedある新しいPromiseを返すことで、データのないあなたが期待しているとはいえ、あなたのコントローラが、結局解雇されます。例えば

$routeProvider.when('/warrantyResult', { 
    templateUrl : 'partials/warranty-result.html', 
    controller : 'WarrantyResultCtrl', 
    resolve : { 
     response : [ 'Warranty', function(Warranty) { 
      return Warranty.sendRequest() 
       .then(null, function(errorData) { 
        // Log an error here? 
        // Or do something with the error data? 
       }); 
     }] 
    } 
}); 

今すぐあなたのコントローラにあなたはresponseundefinedあるかどうかを確認したくなるでしょう。 undefinedの場合は、Warranty.sendRequest()へのコールが失敗したことがわかります。それに応じて行動することができます。

私はこの道を行くことはできませんでした。その代わりに、私はサービスをresolveハンドラに注入し、$httpコールが拒否されるとエラーページにリダイレクトされました。

UPDATE はちょうどあなたが代わりにあなたがあなたのresolveで定義されたresponseを注入しなければならないとき、あなたのコントローラにあなたがWarrantyサービスを注入していることに気づきました。これにより、Warranty.sendRequest()から返されたPromiseが解決されるまでレンダリングが行われなくなります。

関連する問題