2

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

控制器片段:

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);
4

3 回答 3

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

于 2013-11-05T20:24:04.730 回答
2

要记住的关键点是,promise 不会返回值,它们会在值到达时或在值到达时执行一些操作。

该答案基于@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}url$http.get一样。

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

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

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

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

于 2013-12-08T19:32:00.957 回答
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

于 2013-11-05T20:17:40.987 回答