在拦截器中重试Restangular调用

时间:2014-09-08 13:53:08

标签: angularjs restangular

官方restangular文档provides此代码示例在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
});

然而,正如评论中所述,第二次尝试不会触发任何拦截器,因为它直接使用$ http。

有没有办法让第二个请求也通过Restangular管道并执行ErrorInterceptor?

3 个答案:

答案 0 :(得分:4)

实际上,使用 Restangular 进行的请求使用的设计只能解析一次。如果拒绝,您无法重新发送。

我真的不知道你是否想要一个可重复使用errorInterceptor,但服务的工作方式似乎不允许重新构建一个 Restangular对象只需来自response object config

您可以做的一件事是保存对对象的引用,然后在拦截器中使用它。

你应该有你的理由,但我必须用这个来警告你,因为如果失败并且如果它仍然存在,你最终可能会有一个无限的调用,因为 Restangular 总是会调用{ {1}}。

我为演示模拟了一个 Plunkr ,只需打开网络标签并点击按钮,您就会看到所有请求都在那里。

答案 1 :(得分:1)

使用async.retry可能适合您的问题。

假设你的异步函数是:

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);
    });
}

使用retry的示例:

// async will try it 3 times
async.retry(3, apiCall, function(err, result) {
  // do something with the result
});

async.doUntil也会让你感兴趣。

答案 2 :(得分:1)

答案为时已晚,但我找到了解决方案,所以我在这里提一下可能的解决方案。

以下链接中提示您需要使用restangularizeElement

https://github.com/mgonto/restangular/issues/1022

我正在修复一个如下角色的官方例子:

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
});

这样,如果重复请求导致任何错误,它将再次被捕获在restangular错误拦截器中。