Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retry a Restangular call in an interceptor

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?

like image 368
Thomas Stock Avatar asked Sep 08 '14 13:09

Thomas Stock


2 Answers

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.

like image 112
Preview Avatar answered Nov 09 '22 11:11

Preview


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.

like image 1
meriadec Avatar answered Nov 09 '22 11:11

meriadec