Angular 1.5 - 从指令加入对服务器的多个调用

Angular 1.5 - Join multiple calls to server from Directive

我有一个指令,当显示时,将调用一个服务,该服务将 return 承诺在内部对服务器进行 http 调用。

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

有没有一种方法可以加入对服务的所有调用,以便服务只对服务器进行一次调用,或者分批进行多次调用,然后 return 通过承诺将特定数据发送给每个指令? .

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});
  }
});

我发现一种有用的方法是让服务保存异步调用 return 和 return 对后续调用的承诺(如果存在)。对服务器的异步调用完成后,清除保存的承诺,以便对服务的任何后续请求将再次调用服务器。

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;
  }
}])

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

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

.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;
    };
})