【问题标题】:AngularJS $resource interceptorsAngularJS $resource 拦截器
【发布时间】:2014-06-07 02:35:27
【问题描述】:

如何向$resource 调用添加拦截器?

假设我有一个名为Users 的资源工厂,就像这样;

app.factory('Users', ['$resource', 'resourceInterceptor',
  function ($resource, resourceInterceptor) {
    return $resource(
      'users/:user_id',
      {
        user_id: '@id'
      },
      {
        query: {
          method: 'GET', // Not changing the default method, just adding an interceptor
          interceptor: resourceInterceptor // Is there any better way to do this.. like globally?
        },
        save: {
          method: 'POST', // Same here
          interceptor: resourceInterceptor // Again...
        },
        ..., // And so on
      }
    );
  }]);

我的resourceInterceptor 服务看起来像;

app.factory('resourceInterceptor', ['$rootScope',
  function ($rootScope) {
    return {
      request: function () {
        // This function isn't executed at all?
        $rootScope.loading = true;
      },
      response: function () {
        $rootScope.loading = false;
      },
      responseError: function () {
        $rootScope.loading = false;
      }
    };
  }]);

首先,request拦截函数永远不会执行,为什么不呢?

其次,必须将拦截器硬编码到现有的$resource 方法非常乏味,有没有办法更容易地将拦截器分配给特定的$resource 调用,或者甚至可以为所有$resource 调用分配一个拦截器?

【问题讨论】:

  • 你好@Unidan。一年后……你的问题有答案了吗?

标签: angularjs http rest resources interceptor


【解决方案1】:

要在资源中使用拦截器,您应该:

1 - 用你的 request、response、responseError 创建一个 httpInterceptor:

app.factory('myInterceptor', function () {
    //Code
    //return { request:...,
});

2 - 在您的应用中配置此拦截器:

app.config(['$httpProvider', function ($httpProvider) {
    $httpProvider.interceptors.push('myInterceptor');
}]);

现在,当您将 httpProvider 配置为在您注入 $http 的任何地方都有一个拦截器时,您将使用此提供程序,所以...您将执行您的请求、响应和 responseError 功能。

3 - 在资源中使用它。 由于 $resource 使用 $http 并且您在全局范围内配置了 httpProvider ,因此您将在使用资源时调用拦截器的函数。

第二个问题: 您不能将拦截器设置为具体的 $http 对象,它们(拦截器)是全局设置的。

(即使你在你的模块定义之前设置了拦截器,然后你删除它,你也无法知道执行顺序)

如果您不想在每个 $resource 操作中覆盖拦截器属性(正如您在问题中所写),您可以做什么来改进您的拦截器。

app.factory('userLoadingInterceptor', function () {
    //Code
    return {
        request: function(){
            //Check if your are working with a url related with users
            // and if so do things...
        }
});

【讨论】:

  • 是的,但是有没有办法专门确定哪些请求是通过$resource 对象调用的,哪些是普通的$http
  • 作为 $resource 使用 $http 并在 $httpProvider 中定义拦截器。您的拦截器仅在 $http 级别执行操作。我要编辑我的答案
【解决方案2】:

一个通用的 HTTP 拦截器应该做你想做的事。您可以在此处找到示例:Handle HTTP 302 response from proxy in angularjs

【讨论】:

  • $http 服务添加拦截器也会在后台角加载静态资产时触发,这是不希望的。我确定有办法检测它是什么类型的请求,但感觉不对。我想我可以创建一个注入到我的控制器的服务并在那里处理它。
  • 您应该能够将拦截器配置为不根据 URL 处理错误。
【解决方案3】:

来自文档:

拦截器对象有两个可选方法——response和responseError

我不知道您想要实现什么,但通用 HTTP 拦截器可能是一种替代方案。

【讨论】:

  • Afaik,$resource 服务使用$http$http 拦截器 (docs.angularjs.org/api/ng/service/$http#!) 的文档有一个 request 字段。
  • @WillB 你真的认为角度文档是错误的吗? $resource 使用$http,但$resource 使用的拦截器与$http 服务的拦截器没有任何关系。另一种选择可能是 $resource 的装饰器。
  • 不,当然我认为文档没有错。我只是找不到$resource 拦截器的文档,所以我认为它与$http 拦截器相同。 (现在在我的笔记本电脑上找到它,之前在手机上)。那太糟糕了。我想要实现的是仅在使用资源时才显示的加载栏。我来看看装饰器。
猜你喜欢
  • 1970-01-01
  • 2016-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-28
  • 1970-01-01
  • 1970-01-01
  • 2016-09-24
相关资源
最近更新 更多