【问题标题】:AngularJS App: Load data from JSON once and use it in several controllersAngularJS 应用程序:从 JSON 加载数据一次并在多个控制器中使用它
【发布时间】:2016-12-07 06:05:21
【问题描述】:

我正在开发一个使用 AngularJS 作为框架的移动应用程序,目前我的结构类似于:

app.config(['$routeProvider', function($routeProvider) {
    $routeProvider
        .when('/', {
            templateUrl : 'pages/home.html',
            controller  : 'homeCtrl'
        })

        .when('/one', {
            templateUrl : 'pages/one.html',
            controller  : 'oneCtrl'
        })

        .when('/two', {
            templateUrl : 'pages/two.html',
            controller  : 'twoCtrl'
        });
}]);

app.controller('homeCtrl', ['$scope', function($scope) {

}]);

app.controller('oneCtrl', ['$scope', function($scope) {

}]);

app.controller('twoCtrl', ['$scope', function($scope) {

}]);

然后我用ng-view 显示内容:

<div class="ng-view></div>

一切运行良好,但我需要从 JSON 文件加载数据以填充应用程序的所有内容。我想要的是只进行一次AJAX 调用,然后通过我所有不同的控制器传递数据。在我的第一次尝试中,我想创建一个内部带有$http.get() 的服务并将其包含在每个控制器中,但它不起作用,因为每次我注入和使用该服务时它都会发出不同的 ajax 请求。由于我是使用 angular 的新手,我想知道在不搞砸的情况下,实现这一目标的最佳方式或更“角度方式”是什么。

编辑:我正在添加服务的代码,这只是一个简单的$http.get请求:

app.service('Data', ['$http', function($http) {
    this.get = function() {
        $http.get('data.json')
        .success(function(result) {
            return result;
        })
    }
});

【问题讨论】:

  • 示例代码中缺少您的服务,这将是在这里看到的最有用的内容。
  • @Didier 我建议您将代码文件拆分为不同的控制器,并使用服务来获取此数据。查看我的服务代码答案

标签: javascript angularjs ng-view


【解决方案1】:

初始化一次promise,并返回一个对它的引用:

不需要初始化另一个promise。 $http 返回一个。

只需在您的承诺上添加.then() 电话以修改结果

angular.module('app', [])
  .service('service', function($http){
    this.promise = null;
    function makeRequest() {
         return $http.get('http://jsonplaceholder.typicode.com/posts/1')
             .then(function(resp){
                  return resp.data;
             });
    }
    this.getPromise = function(update){
      if (update || !this.promise) {
         this.promise = makeRequest();
      }
      return this.promise;      
    }
  })

Codepen example

编辑:您可以考虑改用 $http 缓存。它可以达到相同的效果。 From the docs:

如果使用尚未填充的同一缓存发出多个相同的请求,则会向服务器发出一个请求,其余请求将返回相同的响应。

【讨论】:

  • 如果您不需要修改/处理 get 响应返回的数据,这可以正常工作,因为这会返回 promise 本身而不是数据,不幸的是这不是我的情况。感谢您的回复。
  • 这个例子可以扩展来做到这一点:)
  • 是的 它可以扩展,确实这是一个很好的答案我没有选择它作为“接受的答案”的唯一原因是因为 haw-i- 的答案已经考虑了事实可以处理数据。非常感谢,再次感谢。
  • 我对这个答案投了赞成票,因为@DaneMacaulay 付出了更多努力,并通过 codepen 示例展示了这个想法。非常干净高效的方法。
  • 完美运行!是的,您可以更改代码以格式化数据。只需像return myFormatting(resp.data); 一样输入您的电话return resp.data;。 AJAX 只执行一次,数据被“缓存”并在所有控制器中重复使用。
【解决方案2】:

试试这个从 GET 链接获取 JSON 数据:

(function (app) {
    'use strict';

    app.factory('myService', MyService);

    MyService.$inject = ['$q', '$http'];

    function MyService($q, $http) {
        var data;

        var service = {
            getData: getData
        };

        return service;

        //////////////////////////////////////

        function getData(refresh) {
            if (refresh || !data) {
                return $http.get('your_source').then(function(data){
                    this.data = data;
                    return data;
                })
            }
            else {
                var deferrer = $q.defer();
                deferrer.resolve(data);
                return deferrer.promise;
            }
        }
    }

}(angular.module('app')));

现在您可以在控制器文件中添加此依赖项并使用:

myService.getData().then(function(data){
    //use data here 
}, function(err){
    //Handle error here
});

【讨论】:

  • 这就像一个魅力,我想以多种方式解决这个问题,但我从未想过使用单例模式。谢谢!
  • 我收到 this is undefined 的行 this.data = data; ,如果我删除它,那么 GET 请求会发生多次。有什么想法吗?
  • 不需要初始化一个新的promise,因为$http返回一个promise,你可以返回一个promise的引用,答案是正确的,但可以更简洁
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-02
  • 2015-04-01
  • 1970-01-01
相关资源
最近更新 更多