Как запретить angular отображать страницу до тех пор, пока не будут представлены все данные?

У меня следующая проблема: я пытаюсь «объединить» данные из двух коллекций из MongoDB. Все выглядит нормально, пока я не попытаюсь показать некоторые данные из второго запроса, который пришел сразу после первого:

$scope.getData = function() {
 var pipeline, fromDateRangeStatement, toDateRangeStatement, service, joblist;
 service = ($scope.service && $scope.service.value) ? $scope.service.value : {
     $exists: true
 };
 pipeline = $scope.utils.getSessionUsersPipeline($scope.fromDate, $scope.toDate,
     $scope.checkedResults, $scope.checkedStatuses, service, $stateParams, $scope.usersLimit);
 toApi.post("/users/aggregate", {
     pipeline: pipeline
 }).success(function(data) {
     $scope.users = data.data.result;
     for (var i = 0; i < $scope.users.length; i++) {
         var path = "/jobs/" + scope.users[i].id + "/sessions";
         var user = $scope.users[i]
         toApi.get(path).success(function(data) {
             user.error = data.data.records[0].exception // this is not shows up in HTML!
             console.log(data.data.records[0].exception); // but it can be logged!
         })
     }
 })

};

Итак, проблема в том, что $scope.users отображаются на моей странице, а их атрибут error - нет. Похоже, данные отобразились до того, как я изменил атрибуты для каждого пользователя в цикле for. Как с этим можно справиться? Спасибо


person Community    schedule 14.04.2016    source источник
comment
docs.angularjs.org/api/ng/directive/ngCloak   -  person Prasad    schedule 14.04.2016
comment
stackoverflow.com/questions/31083974/ это точно вам поможет   -  person Prasad    schedule 14.04.2016
comment
Спасибо за ответ. Но это не помогло... Он по-прежнему отображает только $scope.users, и только потом он console.log мои данные, что означает, что $scope.users отображались до того, как они обновились...   -  person    schedule 14.04.2016
comment
Вы знаете, что согласно коду вам нужно вызвать ошибку, я думаю, Like // https://docs.angularjs.org/api/ng/service/$http может служить вашей цели   -  person Prasad    schedule 14.04.2016
comment
Спасибо, я удалил вызов .error, чтобы сделать код более маленьким для StackOverflow... Проблема в другом - я не вижу измененные данные в своем HTML   -  person    schedule 14.04.2016
comment
Вы можете поместить свою проблему в plunker? с некоторыми образцами данных я могу взглянуть   -  person Prasad    schedule 14.04.2016


Ответы (3)


Ниже приведены два разных решения


Каждый из ваших запросов GET является асинхронным, поэтому вам нужно дождаться их разрешения. Вы можете обернуть каждый запрос в свое собственное обещание и собрать все обещания так

var promises = [];
for (var i = 0; i < $scope.users.length; i++) {
  promises[i] = new Promise(function (resolve, reject) {
    var path = "/jobs/" + scope.users[i].id + "/sessions";
    var user = $scope.users[i]
    toApi.get(path).success(function(data){
      user.error = data.data.records[0].exception;
      console.log(data.data.records[0].exception);
      resolve(user);
  })
}

Затем используйте Promise.all(). сгруппировать все обещания вместе как одно обещание и дождаться его разрешения.

Promise.all(promises).then(function(users) { 
  $scope.users = users;
});

Краткий пример: http://codepen.io/C14L/pen/QNmQoN


Тем не менее, более простым и лучшим решением было бы отображать пользователей одного за другим по мере возврата их API-вызовов.

for (var i = 0; i < $scope.users.length; i++) {
  var path = "/jobs/" + $scope.users[i].id + "/sessions";
  toApi.get(path).success(function (data) {
      $scope.users[i].error = data.data.records[0].exception;
      $scope.users[i].done = true;
      console.log(data.data.records[0].exception);
  });
}

Просто добавьте в свой шаблон проверку на $scope.users[i].done = true и покажите этот набор данных с ng-show="user.done".

person C14L    schedule 14.04.2016
comment
Кажется простым, но выдает ошибку: TypeError: Невозможно установить свойство «ошибка» неопределенного: по какой-то причине он не может видеть $scope.users - person ; 14.04.2016
comment
Исправлено, по какой-то причине цикл for использовал $scope.jobs.length. Также исправлено /jobs/ + объем. --› /jobs/ + $scope. - person C14L; 14.04.2016
comment
Head Slap Я пропустил асинхронную часть. C14L Большой палец вверх!! :-) - person Prasad; 14.04.2016
comment
Удивительные ребята! Спасибо, вы все мне помогли! Теперь это работает. Я также привязал значение в HTML-коде, теперь оно отображается так, как я хотел! - person ; 14.04.2016

var user = $scope.users[i] присвоить только значение $scope.users[i]. поэтому позже, когда вы сделаете user.error=..., это не изменит $scope. попробуй это:

for (var i = 0; i < $scope.jobs.length; i++) {
  var path = "/jobs/" + scope.users[i].id + "/sessions";
  toApi.get(path).success(function(data){
    $scope.users[i].error = data.data.records[0].exception // this is not shows up in HTML!
    console.log(data.data.records[0].exception); // but it can be logged!
  })
}
person Zhiliang Xing    schedule 14.04.2016

2 элемента о том, как справиться с этим:

Если вы используете {{value}}, замените это на

<span ng-bind="value"></span>

Таким образом, вы не увидите скобок.

Теперь вы хотите дождаться всего вашего запроса, прежде чем что-либо менять, чтобы не отображались частичные данные. Это тоже легко:

var promiseArray = []; 
for (var i = 0; i < $scope.users.length; i++) {
     var path = "/jobs/" + scope.users[i].id + "/sessions";
     var user = $scope.users[i]
     promiseArray.push(toApi.get(path)).success(function(data){
         var result = {i:i, data:data};
         return result
     });
 }
 $q.all(promiseArray).then(function success(result){
     for(var i=0; i < promiseArray.length;i++){
        $scope.users[result.i].error = result.data.data.records[0].exception;
     }
 });

По сути, я жду, пока весь запрос будет изменен, прежде чем изменять какие-либо данные, поэтому это будет выполняться в том же цикле angular. Таким образом, DOM будет обновлен только один раз, и пользователь не увидит никаких частичных результатов.

person Walfrat    schedule 14.04.2016