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

nae*_*ael 5 http angularjs 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;
  });
}
Run Code Online (Sandbox Code Playgroud)

指示:

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
    });
  }
 };
}
Run Code Online (Sandbox Code Playgroud)

有没有办法多次实例化指令,而不必两次在控制器中发出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;
}
Run Code Online (Sandbox Code Playgroud)

更新的指令:

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
    });
  }
 };
}
Run Code Online (Sandbox Code Playgroud)

JB *_*zet 4

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

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

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

    return {
        getData: getData
    };
});
Run Code Online (Sandbox Code Playgroud)