AngularJs、$http 拦截器和 $interval

AngularJs, $http Interceptor and $interval

我想我在 AngularJS 中错误地使用了拦截器。我想使用它们来更改对 $interval 的响应中的特定值,以便它在 UI.

中递增

想法是使用拦截器劫持响应并在响应到达模板之前将 $interval 插入到响应中。好主意,但行不通。

第一个问题是我在尝试重新分配响应中的 属性 时遇到错误。

第二个是拦截器似乎会为所有请求调用,这并不理想,因为我需要更改的只有它的特定响应。这让我相信拦截器是用于身份验证和所有请求所需的东西。

考虑到所有这些,我现在知道拦截器不是可行的方法。

我还应该如何解决这个需要在响应中为某些值添加 $interval 的问题?有几个地方需要这样做,所以我想避免每次都插入 $interval

编辑

到目前为止,这两个答案都很好,现在我有了这个有效的方法,现在它们的值被重新分配了,但是 $interval 不起作用。没有错误,但我的 live 值没有每秒增加。任何更多的帮助都会很棒。

我不完全确定这是 forEach 在遍历 response.data 时的正确位置。这会导致我的 $interval 出现问题吗?

var shepServices = angular.module('shepServices', ['ngResource']);

shepServices.factory('SiloInterceptor', function($q, $interval) {
    return {
        'response': function(response) {    
            if(response.config.url.endsWith('/silos')) {
                angular.forEach(response.data, function (value, key) {
                    $interval(function () {
                      response.data[key].live = response.data[key].live * 2;
                    }, 1000);
                });
            }

            return response;
        }
    };
});

编辑 2

我的数据在 response.data

中看起来像这样
0: 
     quantity: 767.5
1: 
     quantity: 77.5
2: 
     quantity: 80

我想向这个数组添加一个新元素,它是一个 $interval,所以它最终是这样的;

0: 
     quantity: 767.5
     live: //increment $interval value here
1: 
     quantity: 77.5
     live: //increment $interval value here
2: 
     quantity: 80
     live: //increment $interval value here

$interval 正在触发,我可以看到 console.log 的输出,但它没有在响应中注册并递增 UI 中显示的值。响应数组作为 silos 绑定到 $scope。所以我想在我的模板中执行此操作并让 silo.live 值每秒递增。

<span ng-repeat="silo in silos">
    <p class="label label-default">{{silo.live | number}}</small></p>
</span>

编辑 3

这就是我注入拦截器的方式,它不使用经典的 $http 对象,而是通过服务中的 $resource

shepServices.factory('Silo', ['$resource', 'SiloInterceptor',
    function($resource, SiloInterceptor) {
        return $resource("/silos", {word: "@word"}, {
            'query': {
                url:        "/silos",
                isArray:    true
            },
            'forLocation': {
                interceptor: SiloInterceptor,
                url:        "/silos",
                params:     {location: "@location_id"},
                isArray:    true
            },
        })
    }]);

按照在 responseInterceptor 的响应函数中完成的方式在响应处理程序中过滤出您想要的请求。

module.factory('myInterceptor', ['$q', 'someAsyncService', function($q, someAsyncService) {  
    var responseInterceptor = {
        response: function(response) {
            if(response.config.url.startsWith('/api/')) {
              //Do your custom processing here
           }
            var deferred = $q.defer();
            someAsyncService.doAsyncOperation().then(function() {
                // Asynchronous operation succeeded, modify response accordingly
                ...
                deferred.resolve(response);
            }, function() {
                // Asynchronous operation failed, modify response accordingly
                ...
                deferred.resolve(response);
            });
            return deferred.promise;
        }
    };

    return responseInterceptor;
}]);

您可以完全修改拦截器中的响应。在此 fiddle 中,我拦截了用户 API 的响应以注入您的名字。除非您 post 编写代码,否则我们无法告诉您拦截器出了什么问题。

拦截器代码:

app.factory('myHttpInterceptor', function () {
   return {
    'response': function(response) {
      response.data[0].name = 'Jake N (modified by interceptor)';
      return response;
    }
   }
});

关于第二个问题,您可以使用配置对象,以便仅在匹配 url 模式(或使用不同的条件)时修改响应。在这里,我仅在 url 包含 'users':

时才修改 http 响应
app.factory('myHttpInterceptor', function () {
   return {
    'response': function(response) {
      if (response.config.url.indexOf('users') > -1) {
          response.data[0].name = 'Jake N (modified by interceptor)';
      }
      return response;
    }
   }
});

updated fiddle