javascript AngularJS - 使用 $routeProvider:resolve 拒绝 $http 承诺
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16987341/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
AngularJS - rejected $http promise with $routeProvider:resolve
提问by pdegand59
I am trying to use resolvein a $routeProviderto display the new route only when a $httprequest is finished. If the request is successful, the promise resulting from the $http.post() is resolved and the view is rendered. But if the request fails (timeout or internal error for eg.), the promise is never resolved and the the view is never rendered. How can I deal with request failure using resolve?
我试图resolve在 a 中使用$routeProvider仅在$http请求完成时显示新路由。如果请求成功,则 $http.post() 产生的承诺将被解析并呈现视图。但是如果请求失败(例如超时或内部错误),promise 永远不会解决,视图也永远不会呈现。如何使用 处理请求失败resolve?
The most important parts of the code is bellow :
代码中最重要的部分如下:
app.js
应用程序.js
$routeProvider.when('/warrantyResult', {
templateUrl : 'partials/warranty-result.html',
controller : 'WarrantyResultCtrl',
resolve : {
response : [ 'Warranty', function(Warranty) {
return Warranty.sendRequest();
} ]
}
});
controllers.js
控制器.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
服务.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;
}
};
} ]);
I know i could use a promise around the $http call and resolve it even if the request is a failure, but I'm wondering if there is a simpler solution.
我知道我可以在 $http 调用周围使用 promise 并解决它,即使请求失败,但我想知道是否有更简单的解决方案。
Thanks for reading and, hopefully, helping :)
感谢阅读,希望能有所帮助:)
回答by robertklep
I think the only way to do it from resolveis to manually resolve the promise returned by Warranty.sendRequestand rewrap it in a new promise:
我认为唯一的方法resolve是手动解析返回的承诺Warranty.sendRequest并将其重新包装在新的承诺中:
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;
} ]
}
In WarrantyResultCtrl, you could check if an error occurred and generate a redirect.
在 中WarrantyResultCtrl,您可以检查是否发生错误并生成重定向。
EDIT: much cleaner solution:
编辑:更清洁的解决方案:
// WarrantyCtrl
$scope.$on('$routeChangeError', function() {
// handle the error
});
$scope.submitWarranty = function() {
$scope.loading = true;
Warranty.setRequestData($scope.data);
$location.path('/warrantyResult');
};
回答by Steve J
What I have found is that the controller is not fired at all if the Promiseis rejected, and your view is never rendered--same as you.
我发现是控制器完全不解雇如果Promise是rejected,你的看法是从来没有渲染-你一样。
What I also discovered is that if you handle the Promisewith a .then()in your $routeProvider's resolve, the .then()will return a new Promisethat is resolvedand your controller is fired after all, albeit without the data you are expecting.
我还发现,如果您在's 中Promise使用 a处理,则将返回一个新的is并且您的控制器最终会被触发,尽管没有您期望的数据。.then()$routeProviderresolve.then()Promiseresolved
For example:
例如:
$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?
});
}]
}
});
Now in your controller you will want to check whether responseis undefined. If it is undefinedthen you'll know that the call to Warranty.sendRequest()failed, and you can act accordingly.
现在在您的控制器中,您将要检查是否response为undefined。如果是,undefined那么您就会知道调用Warranty.sendRequest()失败,您可以采取相应的行动。
For what it's worth, I did not go this route. Instead, I injected the $locationservice into the resolvehandler and redirected to an error page if the $httpcall gets rejected.
对于它的价值,我没有走这条路。相反,如果调用被拒绝,我将$location服务注入resolve处理程序并重定向到错误页面$http。
UPDATEJust noticed that in your controller you are injecting the Warrantyservice when you should instead be injecting the responsethat you defined in your resolve. That will prevent your view from rendering until the Promise returned from Warranty.sendRequest()is resolved.
更新刚刚注意到,在您的控制器中,您正在注入Warranty服务,而您应该注入response您在resolve. 这将阻止您的视图呈现,直到从返回的 PromiseWarranty.sendRequest()得到解决。
回答by pdegand59
After deep searching, I could not find a solution for this problem.
经过深入搜索,我找不到解决此问题的方法。
I decided to drop the resolve statment in my route definition and I use the following snippet of code in the WarrantyCtrl.
我决定在我的路由定义中删除解析语句,并在 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');
});
}
};
Not very clever, but works as intented ... If someone still have the solution for the original problem, I would be very pleased to read it !
不是很聪明,但按意图工作......如果有人仍然有原始问题的解决方案,我会很高兴阅读它!

