Чи існує спосіб у AngularJS визначити константи з іншими константами?


77

Я намагаюся визначити константи з іншими константами, але, здається, це неможливо зробити, оскільки початкова константа не готова, коли потрібна необхідна константа. Я хочу бути впевненим, чи це взагалі неможливо.

В даний час у мене є константи таким чином:

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')
    ;

Другі дві константи - це те, що я хочу досягти.

Відповіді:


45

Спосіб 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 не працює для константи. Перевірте цю скрипту, щоб побачити, для яких методів працює 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, перегляньте цю публікацію .


147

Простий спосіб зробити це так:

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;
});

Кредити: посилання


3
@Helzgate Це не те, що говорив @ gabn88. Функція, якій передається, myApp.constant- це Вираз функції з негайним викликанням або IIFE. Він називає себе, тому вам не потрібно! Це виглядає наступним чином : (function (params) {//do stuff})(). Зверніть увагу на дужки навколо виразу функції та додаткового набору в кінці.
daemonexmachina

@Helzgate Константа з іменем RESOURCES, отже, не буде виразом функції, а об'єктом, повернутим цією функцією.
daemonexmachina

2
Найкраща відповідь.
Jelle Oosterbosch

2
Чи не повинен стояти ;крапка з комою після поверненого об'єкта, наприклад: return { ..... };Я знаю, що технічно вам не потрібна точка з двокрапкою, хоча на основі автоматичної вставки крапки з комою, як це посилання - Але що найкраща практика?
redfox05

Для ясності інших, якщо вам все одно доведеться це зробити, RESOURCES().USERS_DOMAINпрочитайте коментарі вище про вираз функції відразу ж викликаного (IIFE). Я припускаю, що це було те, що було вилучено у коментарі Helzgate щодо того, що було видалено?
redfox05

13

Я роблю це так:

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

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

constants.factory('Constants', ["Independent", function(I) {
   return {
      ANSWER_TO_LIFE: I.C1
   }
}]);

@Beterraba. Не могли б ви детальніше це сказати? Куди піде цей код? Дякую. Mark
mark1234

@ mark1234 Цей код можна передати куди завгодно. Я люблю розміщувати це у своєму файлі служб. Ви повинні пам’ятати про те, щоб включити constantsмодуль до основного модуля.
Бетерраба

8

Поки вам не потрібен доступ до вашої константи в постачальниках, це має працювати нормально:

.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) {
 })

Ця відповідь повинна отримати більше любові :). Спасибі;)
Ніку Сурду

4

Я не можу точно сказати, чи можливо це (не) можливо. Але обхідним шляхом було б визначити базові константи як звичайні константи, а вищі - як служби, що використовують закриття, щоб переконатися, що їх неможливо змінити.

Грубий приклад:

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();

Це не дуже елегантно, але це повинно зробити роботу.


3

Рішення, надане @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 настільки крутий, що ви навіть можете змінити константи.


1
Як доповнення. Вам потрібно оголосити, for (prop in RESOURCES) {використовуючи var або let, like for (let prop in RESOURCES) {.
josivan
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.