遍历Angular Factory的JSON数据

时间:2013-11-05 19:59:20

标签: angularjs

我有一个角度控制器,它使用工厂从JSON文件返回响应。 当我尝试遍历返回的数据时,我在注释中看到以下错误。 但是,如果我在角括号内使用HTML中的realArticleData对象,它会完美地横向移动。我认为这与工厂退回的承诺有关,但我不确定。

Controller Snippet:

function SpecialOrderItemsCtrl($scope, $location, articleDataService) {
    $scope.realArticleData = articleDataService.getArticles();
    //This throws TypeError: Cannot read property 'thdCustomer' of undefined
    $scope.custInfo = $scope.realArticleData.articles.thdCustomer;
}

HTML代码段:

<div ng-controller=SpecialOrderItemsCtrl>
<label>Raw Article JSON</label>
<p>{{realArticleData}}</p>
<label>Json transversed by one level</label>
<p>{{realArticleData.articles}}</p>
<label>THD CUstomer </label>
<p>{{realArticleData.articles.thdCustomer}}</p>
</div>

厂:

function articleDataService($rootScope, $http) {
    articleDataService.data = {};
    articleDataService.getArticles = function() {
    $http.get('articleData.json')
        .success(function(data) {
            articleDataService.data.articles = data;
        });
        return articleDataService.data;
    };
    return articleDataService;
}
sendDesign.factory('articleDataService', articleDataService);

3 个答案:

答案 0 :(得分:4)

你正在处理承诺。因此,您需要异步处理它们。 如在

angular.module('plunker', []).controller('SpecialOrderItemsCtrl', ['$scope', 'articleDataService',  function($scope, articleDataService){
  // when promise is resolved, set the scope variable
  articleDataService.getArticles().then(function(articles){
      // store any data from json that you want on the scope for later access in your templates
      $scope.articles = articles;
  })
}]).factory('articleDataService',['$http', '$q', function($http, $q){
  var data = null;
  return {
    getArticles: function() {
      var promise;
      if(data === null) {
        promise = $http.get('articleData.json').then(function(response){
          // cache the response
          data = response;
          return response;
        });
      } else {
        var deferred = $q.defer();
        // promise is immediately resolved with the cached data
        // this way both cached and async data can be handled consistently
        promise = deferred.promise;
      }
      return promise;
    }
  } ;
}]);

Plunkr链接:http://plnkr.co/edit/7Oas2T

答案 1 :(得分:2)

将您的服务更改为:

articleDataService.getArticles = function() {
    $http.get('articleData.json').then(function(result) {
        return result.data
    });
}

在你的控制器中:

articleDataService.getArticles().then(function(data) {
    $scope.realArticleData = data;
    $scope.custInfo = $scope.realArticleData.articles.thdCustomer;
});

你需要按照承诺模式回到控制器,否则你不会等待你的电话完成,你将收到undefined

答案 2 :(得分:2)

要记住的关键点是,承诺不返回值,当值或值到达时,它们使用值执行某些操作。

这个答案是基于@VladimirGurovich和@tymeJV的答案。

这是一个简单的工厂:

var app = angular.module('myApp', []);    

app.factory('Names', ['$http', function($http) {
  return {
    url: 'names.json',
    fetch: function() {
      return $http.get(this.url, {cache: true}).then(function(json) {
        return json.data;
      });
    }
  };
}]);

Names工厂本身返回一个对象。 fetch方法从$http.get返回承诺链。这使用.then()而不是.success(),因此结果可以链接。工厂可以直接返回$http承诺,但给我的操作命名似乎更清晰。

@ VladimirGurovich的回答是手动处理缓存,但Angular可以为我们做这件事,只需将{config: true}等配置对象和$http.get一起发送到网址。

这是一个简单的小控制器,它依赖于来自Names工厂的数据:

app.controller('MainCtrl', ["$scope", "Names", function($scope, Names) {
    Names.fetch().then(function(data) {
        $scope.names = data.names;
    });
}]);

Names.fetch()承诺完成时,$scope.names将填充返回的数据。

这是一个基于此的Plunker:http://plnkr.co/edit/nMx1XL