My angular app doesn't handle the errors in $http calls.
I have a $httpProvider where I return $q.reject(response) in errorResponse as required by documentation. In the console the angular just puts angular.min.js:99 GET http://localhost:8080/my/api 500 (Internal Server Error).
Code
console.log('before');
$http.get('/my/api', function(response){
console.log('ok');
console.log(response);
}, function(response){
console.log('not ok');
console.log(response)
});
console.log('after');
I just get 'before', 'after' and the message above.
Also in the network tab I get the expected response from server with status 500 and a json content in the body.
Except for the $httpProvider's errorResponse without a return $q.reject(), what could be the problem?
You have syntactical mistake, you should use .then function and then put success & error callback to them.
Code
$http.get('/my/api').then(function(response){
console.log('ok');
console.log(response);
}, function(response){
console.log('not ok');
console.log(response)
});
What I understood by your code/question is, you are expecting to get error callback function to execute, but it is not doing that. If I missed something then do ask same in comments.
Related
I am using $http to make a call. Based on the successful result of the call I may decided to throw an error/reject and have it trickle down to the next call as an error. However if an error is thrown it just halt the process. How can I force the $http promise to reject without wrapping it in some $q code?
// A service
angular.module('app').factory('aService', function ($http, config) {
return {
subscribe: function (params) {
return $http({
url: '...'
method: 'JSONP'
}).then(function (res) {
// This is a successful http call but may be a failure as far as I am concerned so I want the calling code to treat it so.
if (res.data.result === 'error') throw new Error('Big Errror')
}, function (err) {
return err
})
}
}
})
// Controller
aService.subscribe({
'email': '...'
}).then(function (result) {
}, function (result) {
// I want this to be the Big Error message. How do I get here from the success call above?
})
In the above code I would like the Big Error message to end up as a rejected call. However in this case it just dies with the error. This is how I handle things in say Bluebird but it's a no go here.
Ti continue the Chain in a rejected state just return a rejected promise $q.reject('reason') from your $http result something like
$http.get(url).then(
function (response){
if(something){
return $q.reject('reason');
}
return response;
}
)
That way you'll get a a rejected promise and can react to it even when the api call is successful.
I use the the simplest $http.get().then construction, but errorCallback is never called (checked with 500 and 404 error code)
$http.get(url,{cache: pageCache}).then(
function(data){
console.log('getPage.SUCCESS');
console.log(data);
console.log(data.data);
},
function(data){
console.log("ERROR");
console.log(data);
}
);
HTTP HEADERS
I also tried success/error - but the same issue is arrised
As described here, interceptor's responseError function have to be ended with return $q.reject(rejection);
One of my interceptors didn't follow this rule and cause all this mess
It may be that you are using the .then function which returns an object called response that contains several objects one of which is data.
The following is an example from https://docs.angularjs.org/api/ng/service/$http
$http({
method: 'GET',
url: '/someUrl'
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
The response object contains a status object, angular uses this to run either the success callback or the error callback.
Then to access your data object use response.data, or what I like to do is have a service that returns only what I need to avoid confusion in the controller.
Currently I've got this:
$http({
method: 'POST',
url: 'http://api-endpoint/somescript/',
data: formData,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(function (response) {
console.log(response);
});
If the script on the other end works out ok, then gets called. However, let's say the script on the server end has some sort of error that's not properly caught. If I make up an error by tossing in some garbage call like asdfasdf(), the then function isn't called, and instead I get this in the browser console:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at http://api-endpoint/somescript/. (Reason: CORS
header 'Access-Control-Allow-Origin' missing).
How do I catch this in the Angular code so I can handle it in a user-friendly manner?
EDIT: This is not a duplicate, as it is specific to Angular.
The $q.then() method accepts three function parameters, the first being the handler for a successful callbacks, the second being for errors, and the third being for notify. $http leverages $q behind the scenes so this thenable should behave like the documentation suggests.
To handle errors in the above code, just toss in an additional function for error handling as such:
.then(function (response) {
console.log(response);
}, function(response) {
console.log(response);
});
Feel free to browse the $q documentation, specifically The Promise API, for additional details.
To handle this, we will have to add a service/factory to intercept http calls. You can do it like this in your config
$httpProvider.interceptors.push('httpRequestInterceptor');
Now, the above service will be something like this
angular.module("app").factory('httpRequestInterceptor', function ($q) {
return {
'request': function (config) {
// Extract request information
return config || $q.when(config);
},
'responseError': function(rejection) {
// Extract response error information and handle errors
return $q.reject(rejection);
}
}
});
I have URL I'm using that gives a 200 OK status and a JSON payload of {error: "Invalid user"} when you do not provide a correct user on a GET request. When using this URL with Restangular, I would prefer this resulted in an error so I can handle errors in the typical way with promises, otherwise my code is going to be very messy. How would I do this?
You can specify an an response interceptor like this:
app.config(function(RestangularProvider) {
// add a response intereceptor
RestangularProvider.addResponseInterceptor(function(data, operation, what, url, response, deferred) {
// check the response if it contains error or not.
if (typeof(response.error) !== 'undefined') {
alert('Your authentication Fail!');
return false;
};
return response;
});
});
Hello I am using ngResource $save method and I get two different behaviours, I don't understand why
First I'm using it in this way:
$scope.user = new User($scope.user);
$scope.user.$save(function () {
$window.location.href = //redirection here;
}, function (response) {
$scope.form.addErrors(response.data.errors);
});
Then I have another controller when I'm doing a similar operation, but even getting 404 or 422 errors from the server the first callback is executed and the errors callback is ignored.
Does anyone have any idea of this? I've been searching in Google for hours trying to find more documentation about $save but I'm still stuck with this problem.
Thank you.
Well, the problem was on an interceptor I am using to detect 401 (unauthorized errors)
here is the interceptor, notice that you must return $q.reject(response) otherwise the other callbacks are not called (in my case the error callback in ngResource.$save)
MyApp.config(function ($httpProvider) {
$httpProvider.interceptors.push(function($window, $q) {
return {
'responseError': function(response) {
if (response.status == 401) { // Unathorized
$window.location.href = 'index.html';
}
// return response; <-- I was doing this before cancelling all errors
return $q.reject(response);
}
};
});
});