The official restangular documentation provides this code sample to retry a request in the ErrorInterceptor:
var refreshAccesstoken = function() {
var deferred = $q.defer();
// Refresh access-token logic
return deferred.promise;
};
Restangular.setErrorInterceptor(function(response, deferred, responseHandler) {
if(response.status === 403) {
refreshAccesstoken().then(function() {
// Repeat the request and then call the handlers the usual way.
$http(response.config).then(responseHandler, deferred.reject);
// Be aware that no request interceptors are called this way.
});
return false; // error handled
}
return true; // error not handled
});
However, as it says in the comments, the second attempt will not trigger any interceptors because it uses $http directly.
Is there a way to make the second request also go through the Restangular pipeline and execute the ErrorInterceptor?
Actually, the requests made with Restangular use promises that have been designed to be resolved only once. You can't resend it in case of rejection.
I don't really know if you want a re-usable errorInterceptor
or not, but the way the service works don't seems to allow to re-build a Restangular object simply from the response object config
.
One thing you could do is save the reference to your object and then use it in the interceptor.
You should have your reasons, but I must warn you with this because in case of failure and if it persists, you could end up with an infinite call, since the Restangular will always call the errorInterceptor
.
I've mocked up a little Plunkr for the demonstration, just open your network tab and click the button, you should see all the request goes trough there.
Using async.retry
may fit to your problem.
Let's assume your asynchronous function is :
function apiCall(callback) {
Restangular.all('items').getList()
.then(function (res) {
// all is OK
callback(null, res);
})
.catch(function (err) {
if (err.status === 403) {
// this one will bring async to retry apiMethod
return callback(err);
}
// others errors codes will not call apiMethod again
callback(null);
});
}
Example using retry
:
// async will try it 3 times
async.retry(3, apiCall, function(err, result) {
// do something with the result
});
async.doUntil
could interest you too.
It is too late for an answer, however I found a solution for this, So I am going to mention it here as possible solution.
There is a hint in the following link which says you need to use restangularizeElement
.
https://github.com/mgonto/restangular/issues/1022
I am fixing restangular official example as follow:
Restangular.setErrorInterceptor(function(response, deferred, responseHandler) {
if(response.status === 403) {
refreshAccesstoken().then(function() {
// instead of using $http, I will use restangularizeElement as follow
// I still have no idea how is the best method to repeat the request after restangularized it. I am repeating it with a simple get
var request = Restangular.restangularizeElement('', response.data, url);
request.get().then(function() {});
});
return false; // error handled
}
return true; // error not handled
});
In this way, if repeated request cause any error, it will be caught in restangular error interceptor again.