I am calling a method from the server which returns an error response like (400 & 500 errors) but my AngularJS error callback is not getting called and always the success callback is getting called even though my status code contains 400's or 500's. Can someone please tell what am I doing wrong? Please see the angular & WebAPI code below:
我正在从服务器调用一个方法,该方法返回一个错误响应(400和500个错误),但是我的AngularJS错误回调没有被调用,并且总是调用成功回调,即使我的状态代码包含400或500个错误。有人能告诉我我做错了什么吗?请见下面的角和WebAPI代码:
AngularJS code:
AngularJS代码:
$http.get("/api/employee")
.success(function (data, status, headers, config) {
console.log(data);
return data;
}).error(function (data, status, headers, config) {
alert("error");
return status;
});
Web API code:
Web API代码:
public HttpResponseMessage Get(EmployeeModel employee)
{
if (!ModelState.IsValid)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
//some other code
}
4 个解决方案
#1
16
The problem is having an interceptor, which does not propagate the error properly.
问题是有一个拦截器,它不能正确地传播错误。
When responseError of an interceptor is called it has to propagate the exception up the call stack, so the following function calls / callbacks would know that there is an error coming not a successful response.
当调用拦截器的responseError时,它必须将异常传播到调用堆栈上,因此下面的函数调用/回调将知道出现错误而不是成功的响应。
$httpProvider.interceptors.push(function ($q, $rootScope) {
return {
request: function (config) {
//the same config / modified config / a new config needs to be returned.
return config;
},
requestError: function (rejection) {
return $q.reject(rejection);
},
response: function (response) {
//the same response/modified/or a new one need to be returned.
return response;
},
responseError: function (rejection) {
return $q.reject(rejection);
}
};
});
the point that Matthias mentioned is correct, but it lacks the return element. So if you simply reject in responseError, it doesn't work, you need to return the rejection so the following elements would get notified.
Matthias提到的观点是正确的,但是它缺少return元素。如果你只是在responseError中拒绝,它不起作用,你需要返回拒绝,这样下面的元素就会被通知。
#2
6
I had the same problem, and I'm still figuring this out myself, but I identified a possible problem.
我也有同样的问题,我自己也在想,但我发现了一个可能的问题。
The .error()
callback may be prevented from executing, by a HTTP response intercepter (registered by adding to the $httpProvider.interceptors
array).
通过HTTP响应拦截器(通过添加到$httpProvider.interceptors数组来注册),可以阻止.error()回调的执行。
I was using a module for adding interceptors, and so I removed that and wrote the stuff manually.
我正在使用一个模块来添加拦截器,因此我删除了这个模块并手工编写了这些内容。
#3
1
I never had luck with the .success and .error options and ended up using .then for everything and have yet to have a problem. I should also point out that you can't return values from a promise like you are trying to do. You have to declare a variable with var before entering the promise or assign a new $scope variable within the promise.
我从来没有在。success和。error选项上有什么好运气,最后我用了。then。我还要指出的是,你不能像你试图做的那样从一个承诺中返回值。您必须在输入承诺之前声明一个带有var的变量,或者在承诺中分配一个新的$scope变量。
So, with those changes your code would look like this:
因此,随着这些变化,你的代码会像这样:
var employees = $http({method:'GET', url:'/api/employee');
employees.then(function(data){
$scope.employeeData = data;
}, function(data){
//do error handling here
});
Also, having a centralized method for handling errors can be helpful at times, and that can be done using an httpInterceptor (as detailed here: Handle HTTP 302 response from proxy in angularjs). Doing so would allow you to completely remove the second function in the .then if there is no other error handling to be done, thus saving code and bandwidth.
此外,拥有一个用于处理错误的集中方法有时会很有帮助,并且可以使用httpInterceptor(如本文所述:在angularjs中处理来自代理的HTTP 302响应)。这样做可以使您完全删除第二个函数,然后如果没有其他错误处理,从而节省代码和带宽。
#4
1
I had created a interceptor to capture delay of each HTTP request and faced the same problem. The solution was very simple. Just replace: return response; with return $q.reject(response);. Example:
我创建了一个拦截器来捕获每个HTTP请求的延迟,并且遇到了相同的问题。解决方法很简单。只是替换:返回响应;返回q.reject美元(响应);。例子:
SCM.service('httpService', function($q) {
this.request = function(config) {
if (angular.isObject(config)) {
config.delay = new Date().getTime();
}
return config;
};
this.requestError = function(config) {
if (angular.isObject(config)) {
config.delay = new Date().getTime();
}
return $q.reject(config);
};
this.response = function(response) {
if (angular.isObject(response.config)) {
response.config.delay = new Date().getTime() - response.config.delay;
}
return response;
};
this.responseError = function(response) {
if (angular.isObject(response.config)) {
response.config.delay = new Date().getTime() - response.config.delay;
}
return $q.reject(response);
};
});
SCM.config(function($httpProvider) {
$httpProvider.interceptors.push('httpService');
});
#1
16
The problem is having an interceptor, which does not propagate the error properly.
问题是有一个拦截器,它不能正确地传播错误。
When responseError of an interceptor is called it has to propagate the exception up the call stack, so the following function calls / callbacks would know that there is an error coming not a successful response.
当调用拦截器的responseError时,它必须将异常传播到调用堆栈上,因此下面的函数调用/回调将知道出现错误而不是成功的响应。
$httpProvider.interceptors.push(function ($q, $rootScope) {
return {
request: function (config) {
//the same config / modified config / a new config needs to be returned.
return config;
},
requestError: function (rejection) {
return $q.reject(rejection);
},
response: function (response) {
//the same response/modified/or a new one need to be returned.
return response;
},
responseError: function (rejection) {
return $q.reject(rejection);
}
};
});
the point that Matthias mentioned is correct, but it lacks the return element. So if you simply reject in responseError, it doesn't work, you need to return the rejection so the following elements would get notified.
Matthias提到的观点是正确的,但是它缺少return元素。如果你只是在responseError中拒绝,它不起作用,你需要返回拒绝,这样下面的元素就会被通知。
#2
6
I had the same problem, and I'm still figuring this out myself, but I identified a possible problem.
我也有同样的问题,我自己也在想,但我发现了一个可能的问题。
The .error()
callback may be prevented from executing, by a HTTP response intercepter (registered by adding to the $httpProvider.interceptors
array).
通过HTTP响应拦截器(通过添加到$httpProvider.interceptors数组来注册),可以阻止.error()回调的执行。
I was using a module for adding interceptors, and so I removed that and wrote the stuff manually.
我正在使用一个模块来添加拦截器,因此我删除了这个模块并手工编写了这些内容。
#3
1
I never had luck with the .success and .error options and ended up using .then for everything and have yet to have a problem. I should also point out that you can't return values from a promise like you are trying to do. You have to declare a variable with var before entering the promise or assign a new $scope variable within the promise.
我从来没有在。success和。error选项上有什么好运气,最后我用了。then。我还要指出的是,你不能像你试图做的那样从一个承诺中返回值。您必须在输入承诺之前声明一个带有var的变量,或者在承诺中分配一个新的$scope变量。
So, with those changes your code would look like this:
因此,随着这些变化,你的代码会像这样:
var employees = $http({method:'GET', url:'/api/employee');
employees.then(function(data){
$scope.employeeData = data;
}, function(data){
//do error handling here
});
Also, having a centralized method for handling errors can be helpful at times, and that can be done using an httpInterceptor (as detailed here: Handle HTTP 302 response from proxy in angularjs). Doing so would allow you to completely remove the second function in the .then if there is no other error handling to be done, thus saving code and bandwidth.
此外,拥有一个用于处理错误的集中方法有时会很有帮助,并且可以使用httpInterceptor(如本文所述:在angularjs中处理来自代理的HTTP 302响应)。这样做可以使您完全删除第二个函数,然后如果没有其他错误处理,从而节省代码和带宽。
#4
1
I had created a interceptor to capture delay of each HTTP request and faced the same problem. The solution was very simple. Just replace: return response; with return $q.reject(response);. Example:
我创建了一个拦截器来捕获每个HTTP请求的延迟,并且遇到了相同的问题。解决方法很简单。只是替换:返回响应;返回q.reject美元(响应);。例子:
SCM.service('httpService', function($q) {
this.request = function(config) {
if (angular.isObject(config)) {
config.delay = new Date().getTime();
}
return config;
};
this.requestError = function(config) {
if (angular.isObject(config)) {
config.delay = new Date().getTime();
}
return $q.reject(config);
};
this.response = function(response) {
if (angular.isObject(response.config)) {
response.config.delay = new Date().getTime() - response.config.delay;
}
return response;
};
this.responseError = function(response) {
if (angular.isObject(response.config)) {
response.config.delay = new Date().getTime() - response.config.delay;
}
return $q.reject(response);
};
});
SCM.config(function($httpProvider) {
$httpProvider.interceptors.push('httpService');
});