Барьер между службой, использующей $ http, и контроллером, использующим службу? - PullRequest
0 голосов
/ 25 мая 2018

Предположим следующую фабрику сервисов AngularJS:

function Constants($http) {
    var constants = {
        someFields: someValues
    };
    $http({method: "GET", url: baseUrl + "/constants.json"}).success(
        function (data, status) {
            angular.forEach(data, function (value, key) {
                constants[key] = value;
            });
        }
    );
    return constants;
}

Создает сервис Constants с набором констант.Константы частично жестко запрограммированы и частично загружены из constants.json, расположенного на сервере (эта логика не обсуждается).Эта служба затем используется в контроллере:

function SettingsController($scope, $rootScope, Constants) {
    $scope.someProperty = Constants.somePropertyFromConstantsJson;
    ...

Я понимаю, что $http вызовы являются асинхронными.Это означает, что нет никакой гарантии, что свойства из constants.json в примере будут загружены и установлены в Constants до того, как они будут прочитаны в SettingsController.

Как я могу предоставить такую ​​гарантию?Как можно инициализировать SettingsController только после завершения вызова $http в Constants?

UPD: Дело, о котором я говорю, является частью более крупного проекта.Я хочу избежать больших изменений во всей кодовой базе, поэтому мне нужно, чтобы Constants оставался объектом, свойства которого доступны через . или [].Вот почему я рассмотрю варианты, которые не соответствуют этому желанию, в крайнем случае.

UPD2: Я проверил вопрос, помеченный как дубликат.На самом деле я понимаю, что $http - это асинхронная операция, и я не собираюсь извлекать локальное состояние обратных вызовов в конструктор фабрики Constants.Код конструктора Constants делает это, но я согласен с его рефакторингом (пока не будет сохранен тип сервиса Constants и его свойства).Я просто хотел, чтобы Angular создал Constants сервис после вызова Http.Какая-то асинхронная инициализация сервиса.Я думаю, что мое желание не противоречит асинхронному характеру вещей, поправьте меня, пожалуйста, если я ошибаюсь.

1 Ответ

0 голосов
/ 25 мая 2018

Сделайте доступ к константе асинхронным, вместо того, чтобы выставлять константы напрямую, скрывайте их за обещанием.

Что-то вроде этого:

function Constants($http, $q) {
  var constants = {
    someFields: someValues
  };

  const defer = $q.defer();

  $http({
    method: "GET",
    url: baseUrl + "/constants.json"
  }).success(
    function(data, status) {
      angular.forEach(data, function(value, key) {
        constants[key] = value;
      });
    }
  ).then(() => defer.resolve(constants));


  return {
    whenLoaded: () => defer.promise;
  };
}


function SettingsController($scope, $rootScope, Constants) {
  Constants.whenLoaded().then((constants) => $scope.someProperty = constatns);
}
...