【问题标题】:Reading data from JSON file in Angularjs using a Promise使用 Promise 从 Angularjs 中的 JSON 文件读取数据
【发布时间】:2015-12-13 04:02:45
【问题描述】:

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

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

那么我该如何解决呢?以及为什么我在控制台中看不到“正在测试...”的消息?

【问题讨论】:

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


    【解决方案1】:

    您应该在收到回复时解决承诺。

    deferred.resolve(data)
    

    理想情况下,您不应该遵循您正在做的方法,当您处理已经返回 Promise 的 $http.get 时,创建新的 Promise 被视为反模式,您可以利用该 Promise。所以基本上你需要清理你的工厂。通过在其上返回$http.get 对象和.then 函数(also .success & .error methods are deprecated)。 then 的第一个函数将在收到数据时被调用,否则错误函数将被调用。基本上为了解决或拒绝承诺,您需要从承诺返回数据,这将调用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 语句

    【讨论】:

    • 感谢您的帮助我改变了我的工厂以使用您所说的 get 方法返回的承诺,但我安慰我仍然得到那个 Promise 对象,我想获得内容控制台打印的json文件的
    • @AimadMAJDOU 看到您对异步调用及其工作原理感到困惑.. 在 ajax 完成之前您无法获得 $scope.listAuthors 的值..您需要放置 console.log 工厂方法调用 @ 987654340@函数..还需要在调用topAuthorsFactory.getList()方法时删除不必要的赋值..查看更新的答案以获得更详细的版本。
    【解决方案2】:

    试试这个:

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

    你必须解决promise才能获取数据。

    【讨论】:

      【解决方案3】:

      第一个问题是您立即记录承诺本身,而不是它的分辨率值。第二个是你甚至没有解决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 函数以使用承诺链。

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

      【讨论】:

      • 谢谢你的回答我按照你说的做了,我使用了$http.get函数中的promise ,但是在控制台中我得到Null,从中我了解到里面的代码then 方法没有改变$scope.listAuthors 变量(我试图在then 函数中记录topAuthorsList 变量,并且我在控制台上打印了json 文件) 我该怎么做解决这个问题?
      • @AimadMAJDOU then 中的回调函数在 promise 解决时被调用。这总是发生在 Promise 创建之后。您必须等待回调并使用回调函数中的值。这就是 promise 的工作原理。 Promise 意味着稍后将在回调中提供一个值。
      猜你喜欢
      • 2014-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-01
      • 2014-09-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多