Есть ли способ в AngularJS определять константы с другими константами?

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

В настоящее время у меня есть константы таким образом:

angular.module('mainApp.config', [])
    .constant('RESOURCE_USERS_DOMAIN', 'http://127.0.0.1:8008')
    .constant('RESOURCE_USERS_API', 'http://127.0.0.1:8008/users')
    // Specific routes for API
    .constant('API_BASIC_INFORMATION', RESOURCE_USERS_API + '/api/info')
    .constant('API_SOCIAL_NETWORKS', RESOURCE_USERS_API + '/api/social')
    ;

Вторые две константы - это то, что я хочу выполнить.


person raulricardo21    schedule 28.08.2013    source источник


Ответы (6)


Способ AngularJS для определения зависимостей между контроллерами, службами и другими — это внедрение зависимостей (DI). Итак, если у вас есть контроллер A, который зависит от службы B, вам придется создать его следующим образом:

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

myApp.controller("aCtrl", function(serviceB){
    // Controller functionally here
});

Видите ли, AngularJS проверит зависимость serviceB и найдет сервис, который вы создали с этим именем. Если вы не создадите его, вы получите сообщение об ошибке.

Итак, если вы хотите создать константу A, которая зависит от константы B, вам нужно будет указать angular, что A зависит от B. Но константа не может иметь зависимости. Константа может возвращать функцию, но DI не будет работать для константы. Проверьте этот Fiddle, чтобы увидеть, для каких методов работает DI.

Итак, отвечая на ваш вопрос, вы не можете определить константу с другими константами.

Но вы можете сделать это:

angular.module('projectApp', [])
  .constant('domain', 'http://somedomain.com')
  .constant('api', '/some/api/info')
  .service('urls', function(domain, api) {this.apiUrl = domain + api;})

  .controller('mainCtrl',function($scope,urls) {

      $scope.url = urls.apiUrl;

  });

Проверьте эту скрипту, чтобы убедиться, что она работает:

Если вы хотите узнать больше о DI, прочтите этот публикацию.

person lao    schedule 08.05.2014

Простой способ сделать это выглядит следующим образом:

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

myApp.constant('RESOURCES', (function() {
  // Define your variable
  var resource = 'http://127.0.0.1:8008';
  // Use the variable in your constants
  return {
    USERS_DOMAIN: resource,
    USERS_API: resource + '/users',
    BASIC_INFO: resource + '/api/info'
  }
})());

И используйте константы следующим образом:

myApp.controller("ExampleCtrl", function(RESOURCES){
  $scope.domain = RESOURCES.USERS_DOMAIN;
});

Кредиты: ссылка

person Linkmichiel    schedule 24.10.2014
comment
@Helzgate Это не то, что говорил @gabn88. Функция, передаваемая в myApp.constant, представляет собой немедленно вызываемое функциональное выражение или IIFE. Он называет себя так что вам не нужно! Выглядит это так: (function (params) {//do stuff})(). Обратите внимание на круглые скобки вокруг выражения функции и дополнительный набор в конце. - person daemonexmachina; 22.09.2015
comment
@Helzgate Константа с именем RESOURCES, следовательно, будет не выражением функции, а объектом, возвращаемым этой функцией. - person daemonexmachina; 22.09.2015
comment
Лучший доступный ответ. - person Jelle Oosterbosch; 16.12.2015
comment
Разве не должна быть точка с запятой ; после возвращаемого объекта, например: return { ..... }; Я знаю, что технически вам не нужна точка с запятой, хотя на основе автоматической вставки точки с запятой в javascript, Нравится эта ссылка – Но как лучше всего? - person redfox05; 07.03.2016
comment
Для ясности других, если вам в конечном итоге придется делать RESOURCES().USERS_DOMAIN, прочитайте комментарии выше о выражении функции с немедленным вызовом (IIFE). Я предполагаю, что именно об этом был комментарий Хелзгейта, который был удален? - person redfox05; 07.03.2016
comment
если я использую эти константы в конфигурации, то получаю сообщение об ошибке: [$injector:modulerr] Не удалось создать экземпляр модуля - person Mahesh K; 21.12.2016

Я делаю это так:

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

constants.factory("Independent", [function() {
   return {
      C1: 42
   }
}]);

constants.factory('Constants', ["Independent", function(I) {
   return {
      ANSWER_TO_LIFE: I.C1
   }
}]);
person Beterraba    schedule 28.08.2013
comment
@Бетерраба. Не могли бы вы уточнить это? Куда пойдет этот код? Спасибо. Отметка - person mark1234; 18.06.2014
comment
@mark1234 mark1234 Этот код может идти куда угодно. Мне нравится помещать это в мой файл сервисов. Вы должны не забыть включить модуль constants в свой основной модуль. - person Beterraba; 24.06.2014

Пока вам не нужен доступ к вашей константе в провайдерах, это должно работать нормально:

.constant('HOST', 'localhost')
.factory('URL', function(HOST) { return "http://" + HOST })

Если вам нужен доступ к вашим константам в провайдерах, то, я думаю, вам нужно проделать еще кое-что:

.constants('HOST', 'localhost')
.provider('DOMAIN', function(HOST) {
    var domain = "http://" + HOST;
    this.value = function() { return domain };
    this.$get = this.value;
 })
 .provider("anyOtherProvider", function(DOMAINPovider) {
     var domain = DOMAINProvider.value();
 };
 .factory("anyOtherService", function(DOMAIN) {
 })
person Peter Rietzler    schedule 29.05.2015
comment
Этот ответ должен получить больше любви :). Спасибо ;) - person Nicu Surdu; 22.07.2016

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

Грубый пример:

angular.module('myApp').constant('BASE_CONSTS',{
    'FIRST_CONST': '10',
    'SECOND_CONST': '20'
});

angular.module('myServices').factory('MyServiceName', ['BASE_CONSTS', function ('BASE_CONSTS') {
    var SECOND_ORDER_CONST = BASE_CONSTS.FIRST_CONST * 100;
    return {
        GET_SECOND_ORDER_CONST: function() {
            return SECOND_ORDER_CONST;
        }
    }
}]);

И используйте его после внедрения сервиса:

MyServiceName.GET_SECOND_ORDER_CONST();

Это не очень элегантно, но должно выполнять свою работу.

person Thalis K.    schedule 28.08.2013

Решение, предоставленное @Linkmichiel, хорошее, но если вы отчаянно хотите использовать одну константу внутри другой, вы можете объединить их в блоке конфигурации:

angular.module("exampleApp", [])

.constant('BASE_URL', 'http://127.0.0.1:8008')

.constant('RESOURCES', {
  USERS_DOMAIN: '',
  USERS_API: '/users',
  BASIC_INFO: '/api/info'
})

.config(function(BASE_URL, RESOURCES) {
  for (prop in RESOURCES) {
    RESOURCES[prop] = BASE_URL + RESOURCES[prop];
  }
})

.controller('WhatIsInResourcesController', function($scope, RESOURCES) {
  $scope.RESOURCES = RESOURCES;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="exampleApp">
  <div ng-controller="WhatIsInResourcesController">
    <pre>{{ RESOURCES | json }}</pre>
  </div>
</div>

После этапа настройки все константы будут настроены правильно (попробуйте фрагмент кода).

Мораль этой истории такова: Angular настолько крут, что вы даже можете менять константы.

person fracz    schedule 12.07.2016
comment
В качестве дополнения. Вам нужно объявить for (prop in RESOURCES) { с помощью var или let, например for (let prop in RESOURCES) {. - person josivan; 17.02.2017