Приложение AngularJS загружает и обрабатывает данные JSON один раз для нескольких контроллеров

0

Я работаю над Угловым приложением, где я столкнулся с той же проблемой, что и в этом сообщении: Приложение AngularJS: загружайте данные из JSON один раз и используйте его в нескольких контроллерах

У меня есть фабрика, которая читает JSON файл и возвращает весь объект данных. Затем каждый контроллер использует эту фабрику (как услугу?) Для получения данных, но тогда каждый контроллер должен самостоятельно разобрать ее. JSON необходимо искать и обрабатывать, чтобы получить соответствующую полезную нагрузку, например $scope.currentArray = data.someThing.allItems[i]; и т.д., и я, очевидно, не хочу повторять этот код во всех контроллерах.

Кажется, я могу либо найти способ поделиться данными, после того, как, скажем, MainController ("первый") завершил работу над ним, или я могу добавить новый модуль "между" контроллерами и фабрикой. Этот новый модуль - позвольте мне его myProcessService? - тогда будет тот, кто получает объект данных с фабрики и сделает всю обработку там... раз и навсегда. Затем каждый контроллер будет иметь дело только с myProcessService чтобы каким-то образом получить готовые форматированные переменные и массивы и т.д. На их соответствующие области (да, это угловой 1).

Если я попытаюсь привести пример того, как я это делаю до сих пор, может кто-то может помочь мне с необходимыми улучшениями? И я знаю, что сегодня уже неплохо начать использовать модели Angular 2, но, пожалуйста, поймите, что я сначала пытаюсь понять, как работает A1, прежде чем вникать в A2 :)

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 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 relevant:
            var i = getRelevantIndexForToday(new Date());
            $scope.myVar = data.someField; 
            $scope.currentArray = data.someThing.allItems[i]; 
            // etc... you get the drift
        }
    }]);

Редактировать:

Мой ngRouter настроен примерно так. Они заполняют div ng-view в моем index.html. Однако - и, возможно, это нахмурилось? - У меня также есть "MainController", который находится непосредственно в теге body.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>
  • 0
    Итак, вы хотите иметь возможность загружать данные один раз ... и работать только с локальной версией приложения ... это правильно?
  • 0
    Да. Загрузите один раз, и пусть все контроллеры / представления используют одни и те же данные!
Показать ещё 4 комментария

2 ответа

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;  

    }]);

Теперь, когда у вас есть

  • 0
    Это выглядит как раз то, что мне нужно, спасибо! Итак, все это может содержаться в одном и том же модуле (фабрике)? Отлично!
  • 0
    Вы можете создать отдельные фабрики для соответствующих вызовов API. В этом случае вы можете иметь все свои функции, связанные с потоком на этой фабрике. Я также обновлю вопрос с предложением о том, как использовать решимость, которая лучше.
0

Спасибо, что дали ответ в соответствии с моим использованием устаревших методов success и error, 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
        });
    }]);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню