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

Reading data from JSON file in Angularjs using a Promise

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

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

那我该如何解决呢?为什么我在控制台中看不到 "testing..." 消息?

试试这个:

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

您必须履行获取数据的承诺。

您应该在收到回复后解决 promise。

deferred.resolve(data)

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

工厂

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 对象。所以你应该删除那个分配,& $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 语句

第一个问题是您立即记录了承诺本身,而不是它的解析值。第二个是你甚至没有解决 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 已经 returns 一个承诺,并且比 successerror 回调更受欢迎。我改进了您的 getList 函数以使用承诺链。

您可以找到一些使用 promises 的教程: