Сделать данные с фабрики http.get доступными для всего контроллера AngularJS

Я пытаюсь предоставить доступ к файлу json, который содержит информацию о конфигурации для моего проекта (например, номер версии, имя проекта, основной контакт и т. д.). Я создал фабрику, которая извлекает файл json с помощью http.get, затем я могу вытащить это данные в мой контроллер, но я не могу получить к ним доступ из любого места в контроллере.

Я не писал фабрику, я нашел ее как ответ на вопрос другого человека, и она почти полностью скопирована, поэтому, если это неправильный способ выполнить то, что я пытаюсь сделать, пожалуйста, поправьте меня.

вот завод:

app.factory('configFactory', ["$http", function($http) {

    var configFactory = {
        async: function() {
            // $http returns a promise, which has a then function, which also returns a promise
            var promise = $http.get('assets/json/config.json').then(function(response) {
                // The then function here is an opportunity to modify the response
                console.log(response.data.config);
                // The return value gets picked up by the then in the controller.
                return response.data.config;
            });
            // Return the promise to the controller
            return promise;
        }
    };
    return configFactory;

}]);

и вот мой контроллер:

app.controller('footerController', ['$scope', '$rootScope', 'configFactory', function footerController($scope, $rootScope, configFactory) {
    var body = angular.element(window.document.body);
    $scope.onChange = function(state) {
        body.toggleClass('light');
    };
    configFactory.async().then(function(d) {
        $scope.data = d;
        // this console log prints out the data that I am trying to access
        console.log($scope.data);
    });
    // this one prints out undefined
    console.log($scope.data);
}]);

Таким образом, по сути, у меня есть доступ к данным внутри функции, используемой для их извлечения, но не за ее пределами. Я могу решить эту проблему с помощью rootScope, но я стараюсь этого избегать, потому что считаю это бинтом, а не правильным решением.

Любая помощь была бы здоровой, но это мой первый опыт работы с http.get и promises и всем этим, поэтому подробное объяснение было бы очень признательно.

[EDIT 1] Переменными из файла конфигурации нужно будет управлять в веб-приложении, поэтому я не могу использовать константы.


person Colton Williams    schedule 10.06.2016    source источник
comment
Вы не можете получить данные за пределами then, потому что первый console.log вызывается до завершения запроса. Вот как работает асинхронный код.   -  person Estus Flask    schedule 10.06.2016
comment
@estus Итак, что я могу сделать, чтобы это исправить? Я могу добавить функцию тайм-аута, чтобы дать короткую задержку (например, 10 мс), но это кажется хакерским.   -  person Colton Williams    schedule 10.06.2016
comment
Делайте все, что касается configFactory внутри обратного вызова then, это так просто.   -  person Estus Flask    schedule 10.06.2016


Ответы (2)


Не назначайте свои данные ответа переменной области видимости, создайте свойство на самой фабрике и назначьте ответ этому свойству в своем контроллере, когда ваше обещание будет разрешено. Таким образом, вы получите значение во всех других контроллерах.

Я обновил ваш завод и контроллер, как показано ниже.

app.factory('configFactory', ["$http", function($http) {

    var configFactory = {
        async: function() {
            // $http returns a promise, which has a then function, which also returns a promise
            var promise = $http.get('assets/json/config.json').then(function(response) {
                // The then function here is an opportunity to modify the response
                console.log(response.data.config);
                // The return value gets picked up by the then in the controller.
                return response.data.config;
            });
            // Return the promise to the controller
            return promise;
        },
      config:'' // new proprety added
    };
    return configFactory;

}]);

    app.controller('footerController', ['$scope', '$rootScope', 'configFactory', function footerController($scope, $rootScope, configFactory) {
    var body = angular.element(window.document.body);
    $scope.onChange = function(state) {
        body.toggleClass('light');
    };
    configFactory.async().then(function(d) {
       // $scope.data = d;
         configFactory.config=d;
        // this console log prints out the data that I am trying to access
        console.log($scope.data);
    });
    // this one prints out undefined
    console.log($scope.data);
}]);
person Rishi Tiwari    schedule 10.06.2016
comment
Я внес изменения в свой код, и он запускается, но у меня все та же проблема: вызов console.log в последней строке возвращает «undefined», похоже, это не дает мне доступа к данным вне функции. - person Colton Williams; 10.06.2016
comment
В основном вы не пишете никакой логики непосредственно в теле контроллера, скорее всего, у вас есть логика только в какой-то функции. Итак, скажем, если вы хотите использовать эту конфигурацию в какой-либо другой функции, отличной от той, в которой вы ее назначили, вы ее получите. Причина, по которой вы не получаете ее в своем текущем коде, заключается в том, что ваш console.log записывается непосредственно в тело контроллера и выполняется до того, как обещание будет разрешено. Поместите этот код в какую-то функцию и вызовите эту функцию для какого-то события, такого как ng-click или что-то в этом роде. Вы получите данные и не получите undefined - person Rishi Tiwari; 10.06.2016

Вы изучали использование угловых констант? http://ilikekillnerds.com/2014/11/constants-values-global-variables-in-angularjs-the-right-way/ Вы можете использовать их как глобальные переменные, доступные с любого контроллера, без последствий присвоения значений rootScope

person Maxwelll    schedule 10.06.2016
comment
Это сработает, но мне нужно иметь доступ к изменению переменных. Я отредактирую вопрос, чтобы включить это. - person Colton Williams; 10.06.2016