Вызов HTTP-запросов в угловых в пакетной форме?

У меня есть два цикла for и HTTP-вызов внутри них.

for(i=0;i<m;i++) {
  for(j=0;j<n;j++) {
    $http call that uses i and j as GET parameters
    .success(//something)
    .error(//something more)
  }
}

Проблема заключается в том, что она составляет около 200-250 вызовов AJAX, основанных на значениях m и n. Это вызывает проблему сбой браузера при попытке доступа с мобильного устройства. Я хотел бы знать, есть ли способ вызвать HTTP-запросы в пакетной форме (по одному запросу по запросу) и как только эти вызовы закончены, перейдите к следующей партии и т.д.

Ответ 1

То, как я это сделал, выглядит следующим образом (это поможет, когда вы хотите вызвать HTTP-запросы в пакете n requests at a time)

call batchedHTTP(with i=0);

batchedHTTP = function() {
  /* check for terminating condition (in this case, i=m) */
  for(j=0;j<n;j++) {
    var promise = $http call with i and j GET parameters
    .success(// do something)
    .error(// do something else)

    promisesArray.push(promise);
  }
  $q.all(promisesArray).then(function() {
    call batchedHTTP(with i=i+1)
  });
}

Ответ 2

Вы всегда можете использовать соответствующий пакетный модуль HTTP, например angular-http-batcher - который будет принимать все запросы и превращать их в один HTTP-запрос POST перед отправкой это на сервер. Поэтому он уменьшает 250 звонков до 1! Модуль находится здесь https://github.com/jonsamwell/angular-http-batcher, и подробное объяснение этого здесь http://jonsamwell.com/batching-http-requests-in-angular/

Ответ 3

Да, используйте асинхронную библиотеку, найденную здесь: https://github.com/caolan/async

Во-первых, используйте цикл для создания своих задач:

var tasks = []; //array to hold the tasks
for(i=0;i<m;i++) {
  for(j=0;j<n;j++) {
    //we add a function to the array of "tasks" 
    //Async will pass that function a standard callback(error, data)
    tasks.push(function(cb){
       //because of the way closures work, you may not be able to rely on i and j here
       //if i/j don't work here, create another closure and store them as params
       $http call that uses i and j as GET parameters
       .success(function(data){cb(null, data);})
       .error(function(err){cb(err);});
    });
  }
}

Теперь, когда у вас есть массив, полный готовых к обратному вызову функций, которые могут быть выполнены, вы должны использовать async для их выполнения, у async есть отличная возможность "ограничить" количество одновременных запросов и, следовательно, "пакет".

async.parallelLimit(tasks, 10, function(error, results){
    //results is an array with each tasks results.
    //Don't forget to use $scope.$apply or $timeout to trigger a digest
});

В приведенном выше примере вы будете одновременно запускать 10 задач.

В Async есть множество других удивительных возможностей, вы можете запускать все подряд, параллельно, массивы карт и т.д. Следует отметить, что вы могли бы достичь большей эффективности, используя одну функцию и "eachLimit", функция async.