ожидание завершения работы службы http angularJS перед началом следующей итерации цикла

0

Я написал специальный сервис http, который выглядит примерно так:

.service('httpCaller', function ($http, $location) {

  var url = 'myURL'   

  var http = {

    async: function (api) {
        var promise = $http({
            method: 'GET',
            url: url + api,
            dataType: 'json'
        })
        .success(function (call) {
            return call;
        })
        .error(function () {
            $location.path('/search');
        });
        return promise;
    }

  };

  return http;

});

И мне нужно вызвать эту услугу в цикле примерно в сто раз так:

var results = [];
   for (var i = 0; i < someArray.length; i++) {
        httpCaller.async('myAPI').then(function (data) {
            results.push(data);
        });
    }
console.log(results);

Очевидно, мне нужно дождаться завершения каждого HTTP-вызова до начала следующего вызова, иначе, когда я запишу 'результаты' в консоль, он всегда будет пустым, потому что вызовы еще не закончены. Я считаю, что мне нужно использовать...

$q.all()

... но я не могу понять из Angular документации, как интегрировать это с кодом, который я написал. Может ли кто-нибудь объяснить, как мне нужно это делать?

Теги:

2 ответа

1
Лучший ответ

Вы должны сохранить все свои обещания в массиве и передать его функции $q.all. Затем вы можете определить несколько обратных вызовов, которые автоматически вызываются.

Вот пример.

var results = [],
    promises = [];

var promiseSuccess = function (data) {
    results.push(data);
};

var allSuccess = function (data) {
    //data contains array of all return values for promises
};

for (var i = 0; i < someArray.length; i++) {
    promises.push(httpCaller.async('myAPI').then(promiseSuccess));
}

$q.all(promises)
    .then(allSuccess) // called when everything has been loaded
  • 0
    Эй, вы ответили первым, и это помогло мне разобраться, поэтому я дам вам ответ. Но использование «.error» внизу давало мне консольную ошибку: «$ q.all (...). Then (...). Error - это не функция»), и я не знаю почему. Удаление .error исправило это, и все по-прежнему работало. Просто подумал, что дам тебе знать.
  • 1
    Моя error , error и, finally , используется, когда успех возвращает еще одно обещание, я обновил мой пример кода.
1

Вы можете использовать менеджер обещаний $ q.defer(), от отложенного API.

$ q.defer() получить 2 метода:

  • Решение (значение): которые разрешают наше совместное обещание, давая ей окончательное значение

  • reject (причина): которые разрешают ошибку обещания.

Таким образом, вы можете хранить все свои обещания в массиве, затем $q.all() используется для создания обещания, которое будет разрешено, когда все обещания таблицы, переданные как параметр, сами будут разрешены.

контроллер

(function(){

function Controller($scope, Service, $q) {

  var promises = [];

  var defer = $q.defer();

  //Process loop
  for (var i = 0; i < 20; ++i){
    //Fill my promises array with the promise that Service.get() return
    promises.push(Service.get());
  }

  //Resolve all promise into the promises array
  $q.all(promises).then(function(response){
    //Create arr by maping each data field of the response
    var arr = response.map(function(elm){
      return elm.data;
    });
    //Resolve my data when she is processed
    defer.resolve(arr);
  });

  //When the data is set, i can get it
  defer.promise.then(function(data){
    //Here data is an array
    console.log(data)
  });

}

angular
.module('app', [])
.controller('ctrl', Controller);

})();

обслуживание

(function(){

  function Service($http){

    function get(num){
      //Just an example, we return a promise
      return $http.get('path_to_url');
    }

    var factory = {
      get: get
    };

    return factory;

  }

  angular
    .module('app')
    .factory('Service', Service);

})();

Ещё вопросы

Сообщество Overcoder
Наверх
Меню