angularjs 多个控制器相同的 $http 请求缓存

angularjs multiple controllers same $http request cache

正在开发一个需要多个组件显示在同一页面上的应用程序,这些组件需要来自相同 api url.

的数据

根据示例,我有两个组件,一个是面包屑,一个是实际的数据容器,它们都将请求组件的状态以显示相关数据。

数据工厂

angular
    .module('app')
    .factory('data', function($http) { 
        this.getStatus = function() {
            return $http.get('/api/status/');
        }

        return this;
    });

控制器 1

angular
    .module('app')
    .controller('breadcrumb', function(data, breadcrumbProcessor) {
         var _self = this;

         data
             .getStatus()
             .then(function(response) {
                 _self.activeBreadcrumb = breadcrumbProcessor(response.data); 
             });
    });

控制器 2

angular
    .module('app')
    .controller('form', function(data, formProcessor) {
         var _self = this;

         data
             .getStatus()
             .then(function(response) {
                 _self.activeForm = formProcessor(response.data); 
             });
    });

第一个组件将是显示流程阶段的面包屑,而第二个组件将是一个页面,您可以在其中根据阶段显示表单。所以我将要求两个组件相同 api "GET:/api/stage/" 这将向服务器发出 2 个请求。

是否有可能(如果可以,它看起来如何)制作一个拦截器或服务,充当请求的过滤器并将它们合并到一个请求中?

Blitz,为什么你的页面控制器不能调用这两个组件并将数据发送到你的组件?

我的意思是,您需要有一个使用数据工厂的控制器。然后你按范围将数据传递给你的面包屑component/directive,就像你的表单一样。像这样:

angular.module('myApp')
  .controller('ParentController', function (data, $scope) {
    data.getStatus()
             .then(function(response) {
                 $scope.yourData = response.data; 
             });
  })
  .directive('breadcrumb',   function () {
    return {
      restrict: 'A',
      replace: true,
      transclude: false,
      scope: {
        yourData: '='
      },
      templateUrl: 'directives/breadcrumb.html',
      link: function(scope){
        scope.$watch('yourData', function (newValue) {
          scope.activeBreadcrumb = breadcrumbProcessor(newValue);
        });
      }
    };
  })
  .directive('yourForm',   function () {
    return {
      restrict: 'A',
      replace: true,
      transclude: false,
      scope: {
        yourData: '='
      },
      templateUrl: 'directives/your-form.html',
      link: function(scope){      
        scope.$watch('yourData', function (newValue) {
          scope.activeForm = formProcessor(newValue);
        });
      }
    };
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="ParentController">
  <breadcrumb your-data="yourData" />
  <your-form your-data="yourData" />  
</div>

如果可用,您也可以只使用不同的工厂来获取存储的数据:

angular
  .module('app')
  .factory('data', function($http) {
    var vm = this;

    // save to inner variables. those are not
    // accessible from outside the factory
    var statusPromise = $q.defer();

    vm.status = deferred.promise;

    // now, the data is fetched when this factory is
    // initialized (included somewhere)
    $http.get('/api/status/').then(function(res) {
      statusPromise.resolve(res.data);
    });

    return vm;
});

这样,您在请求状态时总能得到承诺。 如果 $http 已经完成,这将 return 一个 已解决的承诺 。 如果没有,这仍然 return 一个 承诺 (稍后会解决)。

这意味着一旦这个工厂被初始化,数据就被获取了。如果您不想要这种行为,您可以使用以下语法创建一个 getStatus 函数:

this.getStatus = function() {
  if (!vm.promiseResolvedAlready) {
    $http.get('/api/status/').then(function(res) {
      statusPromise.resolve(res.data);
      vm.promiseResolvedAlready = true;
    });
  }

  return vm.status;
}

并删除内联 $http 请求。这样,第一次有人调用 getStatus 时,状态实际上会更新承诺。到那时为止,诺言仍未兑现。

使用 angular http 缓存修复了它,如 docs.angularjs.org/api/ng/service/$http 中所述。

我有一个用于注入身份验证令牌的 http 拦截器,我在那里只为 GET 请求设置了 cache = true。

所以现在,我的拦截器有类似

的东西
function request(config) {

    ...

    if(config.method == "GET") {
        config.cache = true;
    }

    ...
}

这似乎恰到好处。