AngularJS:加载延迟JSON并在多个控制器

时间:2016-07-14 21:16:33

标签: javascript angularjs json controller

先生,我对AngularJS有疑问......

我正在尝试在promise中加载一个JSON文件,并将它与两个不同的控制器一起使用......我尝试了很多不同的技术,但是我没有得到它......你能帮助我吗?

//SERVICE
app.service('AllPosts', function($http, $q){
    var deferred = $q.defer();
    $http.get('posts.json').then(function(data){
        deferred.resolve(data);
    });
    this.getPosts = function(){
        return deferred.promise;
    };
    this.getPost = function(id){
        var post={};
        angular.forEach(deferred.promise, function(value) {
            if(value.id == id){
                post=value;
            }
        });
        return post;
    };
});

我正在创建一个调用JSON的服务,就像我为控制器声明我的函数一样......

app.controller('AllCtrl', function($scope, AllPosts){   
    AllPosts.getPosts().then(function(posts){
        $scope.posts = posts.data;
    });
});

在我的第一个控制器中,我调用函数getPosts来获取我的JSON中的所有帖子......

app.controller('PostCtrl', function($scope, AllPosts, $routeParams) {
    AllPosts.getPost($routeParams.id).then(function(the_post){
        $scope.comments = post.comments;
        $scope.title = post.name; 
        $scope.the_content = post.content;
    });
});

在第二个控制器中,我只想要其中一个帖子,所以我调用函数getPost ...

但是我不知道该怎么做,在第一种情况下它适用于所有帖子,但在第二种情况下,nope ...我是Angular的新手,如果你有其他方法,它会是太棒了! 非常感谢!

2 个答案:

答案 0 :(得分:0)

让你的getPost()以你现在需要的方式工作:

this.getPost = function(id) {
  // return same promise
  return deferred.promise.then(function(posts) {
    // but return only one post
    var post = {};
    angular.forEach(posts, function(value) {
      if (value.id == id) {
        post = value;
      }
    });
    return post;

  })

};

$http本身会返回承诺,因此您根本不需要$

app.service('AllPosts', function($http) {

  var postsPromise = $http.get('posts.json').then(function(response) {
    return response.data
  });
  this.getPosts = function() {
    return postsPromise;
  };
  this.getPost = function(id) {
    // return same promise
    return postsPromise.then(function(posts) {
      // but return only one post
      var post = {};
      angular.forEach(posts, function(value) {
        if (value.id == id) {
          post = value;
        }
      });
      return post;

    })

  };
});

答案 1 :(得分:0)

你基本上就在那里,你的代码只有一些放置/订购问题。为了能够在每个控制器中呼叫AllPosts.getPosts(),您需要对服务进行一些调整。

首先,您应该将服务更改为工厂。工厂是singletons,而服务有一个为每个调用/注入调用的实例,几乎就像使用new运算符的类/对象一样。 这样,您可以在所有控制器上拥有一组一致的值,而不会浪费资源为每个控制器实例化新服务。他们都将共享同一个。

其次,您只需要对promise / deferrer模式进行一些更改。见下文:

// Factory - REMEMBER TO INCLUDE LODASH
app.factory('AllPosts', function($http, $q){
    var self = {};
    // create a private posts array to store the cached values
    // The reason for making it private is to prevent you from 
    // directly accessing it rather than using the getter function,
    // potentially giving you the wrong/old values;
    var posts = [];
    var expiry = null;
    self.getPosts = function(){
      var deferred = $q.defer();
      var currentTimeStamp = new Date.getTime();
      // if we have a cached value, that hasn't expired, 
      //get that instead of making another http call
      if(self.posts.length > 0 && currentTimeStamp !== null &&
         currentTimeStamp < expiry) {
        deferred.resolve(self.posts);
        return deferred.promise;
      }
      $http.get('posts.json').then(function(data){
        // cache the values to remove the 
        // need for multiple $http calls
        expiry = new Date().getTime() + (1000 * 60 * 5) // expire in 5 minutes
        posts = data;
        deferred.resolve(data);
      });
      return deferred.promise;
    };
    self.getPost = function(id){
      // Use lodash to simplify your life :)
      return _.find(posts, {id: id});
    }
    return self;
});

如果您要进行大量的集合/数组操作和/或迭代,我强烈建议像lodashunderscore这样的库来帮助您。