Angular — promise в цикле, и как получить данные при каждой итерации?

Добрый день! Подскажите, пожалуйста, как можно при таком коде, в контроллере получать данные из сервиса при каждой итерации.

Роутинг
'profiles': {
  controller: 'profilesList',
  templateUrl: '/partials/profiles/profiles.list.html',
  resolve: {
    profiles: function(dataservice) {
      return dataservice.getProfiles();
    }
  }
}


Сервис:
function getProfiles() {
  var promises = _.range(pages).map(function(page) {
    var deffered  = $q.defer();

    $http
      .get('http://api/v1/profiles?page=' + page)
      .success(function(data) {
        // тут мое непонимание
        deffered.resolve(data);
       })
       .error(function(error) {
        deffered.reject();
       });

    return deffered.promise;
  });

  $q.all(promises).then(function() {
    //
  });
}


И в самом контроллере собственно тоже загвоздка. Я понимаю, что могу дождаться всех промисов и пачкой забрать данные, но суть в том, что профилей очень много, ждать все неумолимо долго. При таком коде, при попытке просто воткнуть return data в success, я буду лицезреть только первый промис, ибо в консоле вижу что данные пришли, и дальше все стопится, нету даже ошибки. Собственно прошу направить на путь истинный. Заранее спасибо!
  • Вопрос задан
  • 4170 просмотров
Решения вопроса 3
@FireGM
На сервере отдавать страницами. В ангуляре проходить по страницам циклом. Потом просто в конец массива добавлять вашу следующую страницу с профилями. Например вот так:
function() {
          return $http.get(''http://api/v1/profiles?page=' + page).then(function (result) {
              $scope.page += 1;
              return angular.forEach(result.data, function (item) {
                  return $scope.profiles.push(item);
                      });
                  });
              };
Ответ написан
benbor
@benbor
Помог ответ - не забудь лайкнуть
1 вариант передать коллбек в Сервис, который будет обрабатывать новые данные, и вызвать сервис не из resolve а из контроллера:
function getProfiles(callback) {
  var promises = _.range(pages).map(function(page) {
    $http
      .get('http://api/v1/profiles?page=' + page)
      .success(function(response) {
        callback(response.data);
       });
  });
};
app.myController(function($scope, myService){
    $scope.profiles; // это отобразить в ng-repeat на вьюхе
    myService.getProfiles(function(newProfiles){
        $scope.profiles += newProfiles;
    });
});

Но, не совсем понятно, раз у Вас много профилей, и у Апи готов Пейджинг, зачем грузить все сразу?
Вариант 2.
function getProfiles(page) {
  return  $http
      .get('http://api/v1/profiles?page=' + page)
      .success(function(response) {
              return response.data;
       });
  });
};
app.myController(function($scope, myService){
    var page = 1;
    $scope.profiles; // это отобразить в ng-repeat на вьюхе
    //здесь прикрутить какой нибудь scroll watcher
    $scrollWatcher.onNewScroll(function(){
          myService.getProfiles(page++).success(function(newProfiles){
               $scope.profiles += newProfiles;
          });
    })
});

PS непомню точно, но какой-то в ангулар есть сервис, отвечающий за прокрутку экрана, scrollWatcher взял из головы, погуглите
Ответ написан
AMar4enko
@AMar4enko
Эм. Я правильно понял, что у вас N страниц, вам нужно для всех скопом забрать данные, но при этом как только приходят данные с одной из страниц, сразу их отдавать в контроллер?
Тогда resolve вам не подойдет - вам нужно дергать сервис напрямую в контроллере.
У $q.defer() есть дополнительный метод notify.
Если честно, я предполагал, что $q.all после резолва каждого промиса делает notify в комбинированный промис - так было бы логично. Увы, это не так. Поэтому можно сгородить свой велосипедик, типа этого codepen.io/AMar4enko/pen/wBKQOy

Но я вижу еще одну проблемку у вас - никто не гарантирует, что страницы придут в запрошенном порядке. Поэтому вам надо дополнительную логику сделать, чтобы уведомлять о получении данных по порядку, в принципе это ерунда.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы