使用Promise从Angularjs中的JSON文件读取数据

时间:2015-12-12 19:26:48

标签: angularjs promise angularjs-controller angular-promise angularjs-factory

我有一个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);
    }

但是在我的控制台中我得到了这个:

enter image description here

那我怎么解决这个问题呢?为什么我没有看到消息"测试......"在控制台?

3 个答案:

答案 0 :(得分:5)

收到回复后,您应该解决承诺。

deferred.resolve(data)

理想情况下,您不应该遵循您正在进行的方法,在您处理已经返回承诺的$http.get时,创建新承诺被视为反模式,您可以利用该承诺。所以基本上你需要清理你的工厂。通过返回$http.get对象& .then功能,(also .success & .error methods are deprecated)。当收到数据时,第一个功能将接到电话。否则错误功能将被调用。基本上为了解决或拒绝承诺,您需要从promise返回数据,这将调用.then方法的后续caller函数。

<强>工厂

myapp.factory('topAuthorsFactory', function($http) {
  var factory = {
    topAuthorsList: false,
    getList: function() {
      //returning promise
      return $http.get('../../data/top_10_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变量,它显然会有promise对象。所以你应该删除那个任务,&amp; $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语句

答案 1 :(得分:1)

试试这个:

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

您必须解决获取数据的承诺。

答案 2 :(得分:1)

第一个问题是您立即记录了承诺本身,而不是它的分辨率值。第二,你甚至不能在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时使用了explicit promise construction antipattern$http已经返回了一个承诺,这比successerror回调更受青睐。我改进了getList函数以使用承诺链。

你可以找到一些关于使用promises的教程: