AngularJS - 多个指令实例多次进行XHR调用

时间:2016-03-09 20:48:23

标签: angularjs http angular-directive angular-controller

我有一个Angularjs指令'ExampleDirective',它有控制器'ExampleController'。控制器定义了两个Promise对象,其中每个Promise对象发出一个Http GET请求并返回响应。

在指令中,我们从promise对象获取响应数据并处理它们以呈现指令。

ExampleDirective在同一个视图中实例化两次,每个实例都会自己进行Http GET请求。这会导致前端性能问题,因为同时发送了两个请求以进行昂贵的数据库调用并从同一个表中读取。

控制器:

angular.module('exampleModule')
  .constant("EXAMPLE_URL", "{% url 'example:get_example' %}")
  .controller('exampleCtrl', ['$scope', '$http', 'EXAMPLE_URL', exampleCtrl]);

function exampleCtrl($scope, $http, EXAMPLE_URL) {
  $scope.examplePromise = $http.get(EXAMPLE_URL).then(function(response) {
    return response.data;
  });
}

指令:

angular.module('exampleModule')
.directive('exampleDirective', ['exampleFactory', 'STATIC_URL',      '$http', '$window', exampleDirective]);

function exampleDirective(exampleFactory, STATIC_URL, $http, $window) {
  return {
    scope: {
      title:'@?',
      loadingImage:'@?',
    },
    restrict: 'AE',
    templateUrl: STATIC_URL + 'example/example-template.html',
    controller: "exampleCtrl",

    link: function (scope, element, attrs) {

     //add default options:
    if (!scope.title) {
      scope.title = 'Example Title';
    }
    if (!scope.loadingImage) {
      scope.loadingImage = '';
    }

    scope.examplePromise.then(function(data) {
      scope.exampleData = data;
      // do something
    });
  }
 };
}

有没有办法多次实例化一个指令但不必在控制器中发出两次Http GET请求?

更新 这就是我所做的,我在答案中提出了一项服务。

服务:

angular.module('chRatingsModule')
.factory('chExampleFactory', ['$http', 'EXAMPLE_URL', chExampleFactory]);

function chExampleFactory($http, EXAMPLE_URL) {
  var api = {}
  var promise = null;
  api.examplePromise = examplePromise; 

  function examplePromise() {
    if (promise == null) {
      promise = $http.get(EXAMPLE_URL).then(function(response) {
        return response.data;
      });
    }
    return promise;
  }

  return api;
}

更新指令:

angular.module('exampleModule')
.directive('exampleDirective', ['exampleFactory', 'STATIC_URL',      '$http', '$window', exampleDirective]);

function exampleDirective(exampleFactory, STATIC_URL, $http, $window) {
  return {
    scope: {
      title:'@?',
      loadingImage:'@?',
    },
    restrict: 'AE',
    templateUrl: STATIC_URL + 'example/example-template.html',

    link: function (scope, element, attrs) {

    exampleFactory.examplePromise.then(function(data) {
      scope.exampleData = data;
      // do something
    });
  }
 };
}

2 个答案:

答案 0 :(得分:4)

第一个解决方案,可能是最好的解决方案:不要从指令进行调用,这应该只是一个图形元素。从控制器进行调用,并将数据作为参数传递给两个指令。

第二种解决方案,在指令中使用服务,并始终返回相同的承诺:

myModule.factory('myService', function($http) {
    var promise = null;
    var getData = function() {
        if (promise == null) {
            promise = $http.get(...).then(...);
        }
        return promise;
    };

    return {
        getData: getData
    };
});

答案 1 :(得分:1)

  

控制器在每个Promise对象中定义两个Promise对象   发出Http GET请求并返回响应。

更改为:

  

SERVICE 定义了每个Promise对象的两个Promise对象   发出Http GET请求并返回响应。

然后,服务可以记住它已经完成了GET,并且每次都要求它们返回结果。