Чтение данных из файла JSON в Angularjs с использованием обещания

У меня есть factory, который дает мне обещание при получении файла json:

myapp.factory('topAuthorsFactory', function($http, $q) {
    var factory = {
        topAuthorsList: false,
        getList: function() {
            var deffered = $q.defer();
            $http.get('../../data/top_10_authors.json')
                .success(function(data, status) {
                    factory.topAuthorsList = data;
                }).error(function(data, status) {
                    deffered.reject('There was an error getting data');
                });
            return deffered.promise;
        }
    };
    return factory;
});

и в моем controller я хочу отобразить содержимое файла json на моей консоли следующим образом:

myapp.controller('topAuthorsController', function($scope, topAuthorsFactory) {


  $scope.listAuthors = topAuthorsFactory.getList().then(function(topAuthorsList) {

      $scope.listAuthors = topAuthorsList;
      console.log('Testing...');

  }, function(msg) {
    alert(msg);
  });

  console.log($scope.listAuthors);
    }

но в моей консоли я получаю это:

введите здесь описание изображения

так как я могу решить это? и почему я не вижу сообщение "тестирование..." в консоли?


person Renaud is Not Bill Gates    schedule 12.12.2015    source источник


Ответы (3)


Вы должны разрешить обещание, когда получите ответ.

deferred.resolve(data)

В идеале вы не должны следовать подходу, который вы делаете, создание нового обещания считается анти-шаблоном, в то время как вы имеете дело с $http.get, которое уже возвращает само обещание, вы можете использовать это обещание. Так что в основном вам нужно очистить свой завод. Возвращая над ним объект $http.get и функцию .then (также методы .success и .error устарели). 1-я функция затем получит вызов, когда данные будут получены, а в противном случае функция ошибки получит вызов. В основном для разрешения или отклонения обещания вам нужно вернуть данные из обещания, которое вызовет последующую функцию .then метода caller.

Фабрика

myapp.factory('topAuthorsFactory', function($http) {
  var factory = {
    topAuthorsList: false,
    getList: function() {
      //returning promise
      return $http.get('../../data/toptopAuthorsFactory.getList()authors.json')
        .then(function(response) {
           var data = response.data;
           factory.topAuthorsList = data;
           //returning data to resolving promise
           return data;
        }, function(error) {
            return 'There was an error getting data';
        });
    }
  };
  return factory;
});

Изменить

По сути, вы назначили вызов фабричного метода topAuthorsFactory.getList() методу $scope.listAuthors, который здесь не требуется, а затем вы печатаете переменную $scope.listAuthors, которая, очевидно, будет иметь объект обещания. Таким образом, вы должны удалить это назначение, и значение $scope.listAuthors будет присвоено из функции .then.

Контроллер

//remove $scope.listAuthors assignment which is incorrect.
topAuthorsFactory.getList().then(function(topAuthorsList) {
   $scope.listAuthors = topAuthorsList;
   console.log('Testing...');

}, function(msg) {
    alert(msg);
});

его асинхронный, который будет оценивать свою функцию, когда асинхронный вызов будет завершен.. оператор console.log

person Pankaj Parkar    schedule 12.12.2015
comment
Спасибо за вашу помощь. Я изменил свою фабрику, чтобы использовать обещание, которое возвращается методом get, как вы сказали, но я утешаю, что все еще получаю этот объект Promise, и я хочу получить содержимое файла json, напечатанное в консоли - person Renaud is Not Bill Gates; 12.12.2015
comment
@AimadMAJDOU вижу, что вы запутались с асинхронным вызовом и тем, как он работает. метод. Посмотрите обновленный ответ для более подробной версии. - person Pankaj Parkar; 12.12.2015

Попробуй это:

.success(function(data, status) {
    factory.topAuthorsList = data;
    deffered.resolve(data);
}).error(function(data, status) {
    deffered.reject('There was an error getting data');
});

Вы должны разрешить обещание получить данные.

person Jeremy Jackson    schedule 12.12.2015

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

getList: function() {
    return $http.get('../../data/top_10_authors.json').then(function(response) {
        return response.data;
    }, function() {
        throw 'There was an error getting data';
    });
}

// ...

$scope.listAuthors = null;
topAuthorsFactory.getList().then(function(topAuthorsList) {
    $scope.listAuthors = topAuthorsList;
    console.log('Testing...');
    console.log($scope.listAuthors);
}, function(msg) {
    alert(msg);
});

Я заметил, что вы использовали явное при использовании $http. $http уже возвращает промис, и это предпочтительнее обратных вызовов success и error. Я улучшил вашу функцию getList, чтобы использовать цепочку промисов.

Вы можете найти учебник по использованию промисов:

person Tamas Hegedus    schedule 12.12.2015
comment
Спасибо за ответ. Я сделал, как вы сказали, и я работал с promise из функции $http.get, но в консоли я получаю Null, из чего я понимаю, что код внутри метода then не изменил переменную $scope.listAuthors (I попытался зарегистрировать переменную topAuthorsList внутри функции then, и я получил файл json, напечатанный на консоли) как я могу это решить? - person Renaud is Not Bill Gates; 12.12.2015
comment
@AimadMAJDOU Функция обратного вызова в then вызывается, когда обещание разрешается. Это всегда происходит позже, чем создание промиса. Вы должны дождаться обратного вызова и использовать значение в функции обратного вызова. Так работают обещания. Обещание означает, что значение будет доступно позже внутри обратного вызова. - person Tamas Hegedus; 12.12.2015