AngularJS app为多个控制器加载和处理JSON数据一次

时间:2016-01-24 22:33:40

标签: javascript angularjs json

我正在开发一个Angular应用程序,我遇到的问题与此帖中的问题大致相同: AngularJS App: Load data from JSON once and use it in several controllers

我有一个读取JSON文件的工厂,并返回整个数据对象。然后,每个控制器使用此工厂(作为服务?)来获取数据,但是每个控制器必须自己选择它。必须搜索和处理JSON以获取相关的有效负载,如$scope.currentArray = data.someThing.allItems[i];等,我显然不想在所有控制器中重复此代码。

对我来说,我可以找到一些方法来分享数据,比如说MainController(“第一个”)已经完成了工作,或者我可以添加一些新的模块“在”控制器和工厂之间。这个新模块 - 我们称之为myProcessService? - 然后是从工厂获取数据对象的那个,并在那里进行所有处理......一劳永逸。然后,每个控制器只处理myProcessService(以某种方式)将准备好格式化的变量和数组等放到它们各自的范围内(是的,这是Angular 1)。

如果我试着举例说明我到目前为止这样做,也许有人可以帮助我进行必要的改进?并且,我知道今天开始使用Angular 2模式是一个好主意,但请理解我在钻研A2之前首先尝试了解A1的工作方式:)

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


app.factory('getDataFile', ['$http', function($http) {
    function getStream(pid) {
        return $http.get("data/" + pid + ".json")
            .success(function(data) {
                    console.info("Found data for pid " + pid);
                    return data;
            })
            .error(function(err) {
                    console.error("Cant find data for pid " + pid);
                    return err;
            });
    }
    return {getStream: getStream};
}]);


app.controller('MainController', ['$scope', 'getDataFile', 
    function($scope, getDataFile) {     
        getDataFile.getStream('10101011').success(function(data) {

            // process "data" into what's relevant:
            var i = getRelevantIndexForToday(new Date());
            $scope.myVar = data.someField; 
            $scope.currentArray = data.someThing.allItems[i]; 
            // etc... you get the drift
        }
    }]);

app.controller('SecondController', ['$scope', 'getDataFile', 
    function($scope, getDataFile) {     
        getDataFile.getStream('10101011').success(function(data) {

            // process "data" into what's relevant:
            var i = getRelevantIndexForToday(new Date());
            $scope.myVar = data.someField; 
            $scope.currentArray = data.someThing.allItems[i]; 
            // etc... you get the drift
        }
    }]);

编辑:

我的ngRouter设置如下。它们填充了我的index.html中的ng-view div。然而 - 也许这是不赞成的? - 我得到一个“MainController”,它直接位于index.html body标记中,这样我就可以在标题部分显示一些数据(来自后端)单页面应用程序。

app.config(function($routeProvider) {

  $routeProvider

  .when('/:id/work/:page_id', {
    controller: 'AssetController',
    templateUrl: 'app/views/work.html'
  })
  .when('/:id/work/', {
    redirectTo: '/:id/work/1'
  })
  .when('/:id/', {
    controller: 'DashController',
    templateUrl: 'app/views/dashboard.html'
  })
  .otherwise({
    redirectTo: '/'
  });

});

和index.html很像这样:

<body ng-app="myApp">

    <div class="container" ng-controller="MainController">

        <h1>Welcome, {{username}}</h1>

        <div ng-view></div>

    </div>
</body>

2 个答案:

答案 0 :(得分:1)

您可以在工厂中添加另一个辅助函数,该函数返回您想要在控制器之间共享的所需对象。

app.factory('getDataFile', ['$http', function($http) {
    function getStream(pid) {
        return $http.get("data/" + pid + ".json")
            .success(function(data) {
                    console.info("Found data for pid " + pid);
                    return data;
            })
            .error(function(err) {
                    console.error("Cant find data for pid " + pid);
                    return err;
            });
    }

    function getCurrent(pid) {
        return getStream(pid).then(function() {
                var i = getRelevantIndexForToday(new Date());

            return  {
                myVar: data.someField,
                currentArray: data.someThing.allItems[i];
            };
        });
    }

    return {
        getStream: getStream,
      getCurrent: getCurrent
    };
}]);

app.controller('MainController', ['$scope', 'getDataFile', 
    function($scope, getDataFile) {     
        getDataFile.getCurrent('10101011').success(function(data) {
            $scope.myVar = data.myVar; 
            $scope.currentArray = data.currentArray; 
            // etc... you get the drift
        }
    }]);

app.controller('SecondController', ['$scope', 'current', 
    function($scope, current) {     
        .success(function(data) {
                        $scope.myVar = data.myVar; 
            $scope.currentArray = data.currentArray;  
        }
    }]);

<强>建议:

另外,我建议你使用resolve,它允许你从你的路线传递数据到你的控制器。

<强>路线:

.when('/:id/work', {
    controller: 'AssetController',
    templateUrl: 'app/views/work.html',
     resolve: {
        // you are injecting current variable in the controller with the data. You can inject this to each of your controller. you dont need to add the whole function in your next route. Just use current
        current: function(getDataFile){
           return getDataFile.getCurrent('10101011');
        }
  })

<强>控制器:

app.controller('MainController', ['$scope', 'current', 
    function($scope, current) {     
        $scope.myVar = current.myVar; 
        $scope.currentArray = current.currentArray;
    }]);

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

        $scope.myVar = current.myVar; 
        $scope.currentArray = current.currentArray;  

    }]);

现在你已经

答案 1 :(得分:0)

感谢您根据我对已弃用的方法successerror使用Subash的回答。但是,我的答案中的代码有些问题,我在#angularjs上得到了一些帮助,所以我想我应该在这里发布更新的代码。

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

myApp.factory('getDataFile', ['$http', function($http) {
    function getStream(pid) {
        // here, using placeholder data URL, just to get some data:
        return $http.get('http://jsonplaceholder.typicode.com/users')
            .then(function(result) {
                    console.info("Found data for pid " + pid);
                    return result.data;
            })
            .catch(function(err) {
                    console.error("Cant find data for pid " + pid);
                    return err;
            });
    }

    function getCurrent(pid) {
        return getStream(pid).then(function(data) {
            var i = 1;  // test
            console.log("myVar = ", data[i].name);
            return  {
                myVar: data[i].name
            };
        });
    }

    return {
        getStream: getStream,
      getCurrent: getCurrent
    };
}]);

myApp.controller('MainController', ['$scope', 'getDataFile', 
    function($scope, getDataFile) {     
        $scope.name = "j";
        getDataFile.getCurrent('10101011').then(function(user) {
            $scope.myVar = user.myVar;

            console.log("controller. myVar = ", user);
            // etc... you get the drift
        });
    }]);