问题
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?
回答1:
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.
回答2:
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.
回答3:
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.
来源:https://stackoverflow.com/questions/25725896/retry-a-restangular-call-in-an-interceptor