【问题标题】:AngularJS : Load defer JSON and Use It between multiple ControllersAngularJS:加载延迟 JSON 并在多个控制器之间使用它
【发布时间】:2016-07-14 21:16:32
【问题描述】:

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

我正在尝试加载一个 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...

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

【问题讨论】:

    标签: javascript angularjs json controller


    【解决方案1】:

    为了让您的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;
    
        })
    
      };
    });
    

    【讨论】:

    • 谢谢你的回答,我不能让它工作,不知道为什么,但我会仔细看看......谢谢;)哦,顺便说一句,小心postPromise和postPromise :)
    • 控制台有什么错误吗?需要隔离什么是有效的或无效的
    • 不,我没有任何错误,但我使用 $q 进行延迟,它现在适用于所有帖子,而不仅仅是一个......:/
    【解决方案2】:

    您基本上就差不多了,只是您的代码存在一些放置/排序问题。为了让您能够在每个控制器中调用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 这样的库来帮助您。

    【讨论】:

    • 哇,感谢您的更改...我稍后再试。我正在学习 Angular,所以我尝试不添加任何其他库,但我会仔细研究 Lodash ......谢谢。而且问题是我已经做过工厂,想学服务,但是我懂啊啊
    • 别担心,angular 有时会有点变幻无常!奇怪的是,在我使用它的这几年里,我很少需要使用服务而不是工厂,但很高兴你在尝试新事物!
    猜你喜欢
    • 2016-10-10
    • 1970-01-01
    • 2014-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-28
    • 1970-01-01
    相关资源
    最近更新 更多