AngularJS - can I skip an interceptor? - angularjs

I have an AngularJS application with an interceptor to display error messages.
Sometimes the error message from the backend needs some front-end treatment to give more context, like changing a "access denied" into "You can't do this because of X".
How can I do this so the interceptor does not get called?
Right now I am endind up with 2 messages. The message from my controller and the message from the interceptor.

Solution:
service.js:
myFunction: function(id) {
return $http.post('myUrl/', {}, {skipErrorInterceptor: true});
}
interceptor.js:
'responseError': function(rejection) {
if (rejection.config.skipErrorInterceptor) {
return $q.reject(rejection);
} else {
... Global message treatment
}
return $q.reject(rejection);
}

Related

ionic http request loading timeout

I am using the following to show a loading screen whenever I am performing a http request however sometimes if there is an error then it will stay loading (because of the backdrop the app becomes unusable). Rather than hide it on every error checker I was wondering if it is possible to call the timeout after 5 seconds?
.config(function($httpProvider) {
$httpProvider.defaults.timeout = 5000;
$httpProvider.interceptors.push(function($rootScope) {
return {
request: function(config) {
$rootScope.$broadcast('loading:show')
return config
},
response: function(response) {
$rootScope.$broadcast('loading:hide')
return response
}
}
})
})
Following Jess's answer it now looks like this :
.config(function($httpProvider) {
$httpProvider.defaults.timeout = 5000;
$httpProvider.interceptors.push(function($rootScope) {
return {
request: function(config) {
$rootScope.$broadcast('loading:show')
return config
},
response: function(response) {
$rootScope.$broadcast('loading:hide')
return response
},
responseError: function(response) {
$rootScope.$broadcast('loading:hide')
return response
},
requestError: function(response) {
$rootScope.$broadcast('loading:hide')
return response
}
}
})
})
However I cannot seem to be able to put an alert in the requestError to inform the user.
Question
How can I implement an alert to notify the user of the error that has occurred?
try adding responseError and requestError so like this:
responseError: function(responseError) {
$rootScope.$broadcast('loading:hide')
return responseError
and do this again with requestError,
This is from the angular http interceptors docs
requestError: interceptor gets called when a previous interceptor threw an error or resolved with a rejection.
responseError: interceptor gets called when a previous interceptor threw an error or resolved with a rejection.
Edit to answer comment:
so if you want to throw a alert on responseError than a add a $rootScope.$broadcast('response:error')
in the responseError function
then in the controller you want to throw the alert in just do a
$scope.$on('response:error', function(){throw the error here});
you can also do the same for requestError
this works because $broadcast -- dispatches the event downwards to all child scopes

Error: promise is not defined

I have a factory and its function is to handle redirect status codes. If it sees that the status code is 302, it will redirect the page to the login page.
app.factory('redirectInterceptor', function($q,$location){
return {
responseError : function(response){
return promise.then(
function success(response) {
if(response.status === 302){
alert("success " +response.status);
$location.path('/login.html');
return response;
}
else{
alert("success " +response.status);
return response;
}
},
function error(response) {
if(response.status === 302){
alert("error " +response.status);
$location.path('/public/login.html');
return $q.reject(response);
}
else{
alert("error " +response.status);
return $q.reject(response);
}
}
);
}
}
});
app.config(['$httpProvider',function($httpProvider) {
$httpProvider.interceptors.push('redirectInterceptor');
}]);
But I get an error once the server returns 302. here it is
Error: promise is not defined
What have I done wrong?
You need to use interceptors
Sometimes you might need to modify HTTP requests and responses. This could be for a variety of reasons such as adding global logic handling for HTTP errors. With interceptors, you can easily accomplish this in your Angular applications.
Refer this: https://egghead.io/lessons/angularjs-using-angularjs-interceptors-with-http
Also see this similar post AngularJS using an interceptor to handle $http 404s - promise not defined error

catching 403 errors in angular and showing a pop up

On our site, I get into this predicament where you basically transfer a project over to another user. When that happens, if the original user tries to view the project he/she just transferred, we give a 403 back because they no longer are the owner of the project. I started to look up interceptors in angular. I hooked up the responseError to just see if it gets called on the 403 like so
.config(($httpProvider) => {
$httpProvider.interceptors.push(function() {
return {
responseError: function(rejection) {
console.log("bad response");
return rejection;
}
}
});
});
So my "bad response" gets called and everything, but I was not sure how I could show a modal view or something at this point that shows the error to the user since this 403 response actually happens on a few of our different resources, not just projects. Any thoughts? Thanks in advance.
If i understand correctly you want to show the error dialog only for some http calls not every call that goes through you interceptor. You could probably try this:-
Set a config for your http calls say handleError:true.
$http.get('myurl', {handleError:true})....
$http.post('myurl',data, {handleError:true})....
etc..
and in your interceptor look for that specific config setting to display the error:-
$httpProvider.interceptors.push(function() {
return {
responseError: function(rejection) {
console.log("bad response");
if(rejection.config.handleError && rejection.status === 403){
//show error dialog
}
return rejection;
}
}
});
Also you could possibly send the status code that needs to be handled as well.
$http.get('myurl', {handleStatus:[403,...]})....
and
$httpProvider.interceptors.push(function() {
return {
responseError: function(rejection) {
if((rejection.config.handleStatus || []).indexOf(rejection.status) > -1){
//show error dialog. probably you could show it in a $timeout to make this async.
}
return rejection;
}
}
});

In angular, how can I catch the moment when an ajax request is successfully sent?

With angular $resource, I would like to fire a callback function when a request is successfully sent to the restful backend. (The backend may take a long time and I only want to know if it received the data I sent.)
The only thing I've found so far is resource.action.$promise['finally'](callback);
I'd be also interested to know when the request could not be sent. (eg. connection problems)
Thanks!
Here is DRY approach :
Build a service intercepting every HTTP requests (like the one defined in the official documentation) :
$provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
return {
// optional method
'request': function(config) {
// do something on success
return config;
},
// optional method
'requestError': function(rejection) {
// do something on error
if (canRecover(rejection)) {
return responseOrNewPromise
}
return $q.reject(rejection);
},
// optional method
'response': function(response) {
// do something on success
return response;
},
// optional method
'responseError': function(rejection) {
// do something on error
if (canRecover(rejection)) {
return responseOrNewPromise
}
return $q.reject(rejection);
}
};
});
Simply put your code inside the desired hooks. You could for instance draw an error modal dialog if the request fails.
Finally, Register it to your application :
app.config(['$httpProvider', function($httpProvider) {
// Add the interceptor to the $httpProvider to intercept http calls
$httpProvider.interceptors.push('myHttpInterceptor');
}]);

Reject from 'response' into 'responseError'

Sometimes, the API I'm using will return 200 ok even though there has been an error. The response JSON object will look something like:
{
error: true
}
I've built a $http response interceptor that simply checks for this error and rejects it. I want it to then jump into my responseError function:
$httpProvider.interceptors.push(function($q) {
return {
response: function (response) {
if (response.data.error) {
// There has been an error, reject this response
return $q.reject(response);
}
return response;
},
responseError: function(rejection) {
// Display an error message to the user
...
return $q.reject(rejection);
}
}
});
Problem is, even after rejecting the response, my responseError function isn't called. It is called on 500 errors etc so I know it's working. I'd expect a rejection to do the same thing.
From the docs:
responseError: interceptor gets called when a previous interceptor threw an error or resolved with a rejection.
Any ideas on what's missing?
Looks like this isn't possible to do. To cut down on duplicate code, simply declare the error handling function separately and reuse it inside the response and responseError functions.
$httpProvider.interceptors.push(function($q) {
var handleError = function (rejection) { ... }
return {
response: function (response) {
if (response.data.error) {
return handleError(response);
}
return response;
},
responseError: handleError
}
});
To add to this answer: rejecting the promise in the response interceptor DOES do something.
Although one would expect it to call the responseError in first glance, this would not make a lot of sense: the request is fulfilled with succes.
But rejecting it in the response interceptor will make the caller of the promise go into error handling.
So when doing this
$http.get('some_url')
.then(succes)
.catch(err)
Rejecting the promise will call the catch function. So you don't have you proper generic error handling, but your promise IS rejected, and that's useful :-)
Should you want to pass the http response to the responseError handler, you could do it like this:
$httpProvider.interceptors.push(function($q) {
var self = {
response: function (response) {
if (response.data.error) {
return self.responseError(response);
}
return response;
},
responseError: function(response) {
// ... do things with the response
}
}
return self;
});

Resources