Angular 1.5 - 从Directive加入对服务器的多次调用

时间:2018-04-07 16:00:52

标签: angularjs angularjs-directive

我有一个指令,如果显示,将调用一个服务,该服务将返回一个承诺,在内部对服务器进行http调用。

该指令用于每一行,因此,如果我有200行,该指令将被调用200次,这将调用服务200次,这将调用服务器200次。

是否有办法加入对服务的所有调用,以便服务只对服务器进行一次调用,或者多次批量调用,然后通过承诺将特定数据返回给每个指令?

Plnkr示例:https://plnkr.co/edit/Sz5W27mirXKER49ORZvo?p=preview

var app = angular.module('plunker', [])
.service('Service', function($http, $q) {
    this.getStatus = function(id) {
          var status = $q.defer();
          // Obviously, this call is never really made on plnkr.com but it shows the issue
          $http({
              url: 'https://httpbin.org/get',
              method: 'GET',
              params: {
                id: id
              }
          }).then(function successCallback(response) {
              status.resolve(response.data.args.id);
          }.bind(this), function errorCallback() {
              status.reject();
          }.bind(this));
        return status.promise;
    };
})
.directive('directive', function() {
    return {
        restrict: 'E',
        replace: true,
        template: '<span>{{ status }}</span>',
        scope: {
            id: "=",
        },
        controller: function($scope, Service) {
            $scope.status = '';
            Service.getStatus($scope.id).then(function (status) {
                $scope.status = "status" + status;
            });
        }
    }
})
.controller('MainCtrl', function($scope) {
  $scope.users = [];
  for (var i = 0; i < 200; i++) {
    $scope.users.push({id : i, name : 'name' + i});
  }
});

2 个答案:

答案 0 :(得分:0)

我发现一个有用的方法是让服务保存异步调用返回的promise,并为后续调用返回该promise(如果存在)。一旦对服务器的异步调用完成,清除已保存的promise,以便对服务的任何后续请求将再次调用服务器。

https://plnkr.co/edit/TXUBV10xOsRl9nscRmRl?p=preview

.service('myService', ['$http', function($http){

  var serverCall = null;
  var callCount = 0;

  return {
    callAsync: callAsync
  };

  function callAsync(){
    if(serverCall == null){
      serverCall = $http({method: 'GET', url: 'https://httpbin.org/delay/3? callCount=' + ++callCount})
      .then(function(response){
        serverCall = null;
        return response.data.args;
     });
    }

    return serverCall;
  }
}])

答案 1 :(得分:0)

@Alex指向正确的方向,使用Async库。我需要使用的是货物控制流程。

现在,指令可以向服务发送请求,该服务将它们分组到一个http请求上,并将响应发送回每个指令。每个指令都会收到请求的结果,但现在,只有1个请求,而不是200个请求。

.service('Service', function($http, $q) {
    this.cargo = async.cargo(function(tasks, callback) {
        var ids = [];
        for (var i = 0; i < tasks.length; i++) {
            ids.push(tasks[i].id);
        }
        $http({
            url: 'https://httpbin.org/get',
            method: 'GET',
            params: {
                ids: ids
            }
        }).then(function successCallback(response) {
            for (var i = 0; i < tasks.length; i++) {
                tasks[i].q.resolve(response.data.args.ids[i]);
            }
        }.bind(this), function errorCallback() {
            for (var i = 0; i < tasks.length; i++) {
                tasks[i].q.reject();
            }
        }.bind(this));
    });

    this.getStatus = function(id) {
        var q = $q.defer();
        this.cargo.push({q: q, id: id})
        return q.promise;
    };
})