Gibt es in AngularJS eine Möglichkeit, Konstanten mit anderen Konstanten zu definieren?

77

Ich versuche, Konstanten mit anderen Konstanten zu definieren, aber es scheint, dass dies nicht möglich ist, da die Anfangskonstante nicht bereit ist, wenn die erforderliche Konstante dies erfordert. Ich möchte sicher sein, dass dies überhaupt nicht möglich ist.

Derzeit habe ich Konstanten auf diese Weise:

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

Die zweiten beiden Konstanten möchte ich erreichen.

raulricardo21
quelle

Antworten:

45

Die AngularJS-Methode zum Definieren von Abhängigkeiten zwischen Controllern, Diensten und anderen besteht in der Abhängigkeitsinjektion (DI). Wenn Sie also einen Controller A haben, der von einem Dienst B abhängt, müssen Sie ihn folgendermaßen erstellen:

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

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

AngularJS überprüft die ServiceB-Abhängigkeit und sucht nach dem Service, den Sie mit diesem Namen erstellt haben. Wenn Sie keine erstellen, wird eine Fehlermeldung angezeigt.

Wenn Sie also eine Konstante A erstellen möchten, die von der Konstante B abhängt, müssen Sie den Winkel angeben, dass A von B abhängt. Eine Konstante kann jedoch keine Abhängigkeit haben. Eine Konstante kann eine Funktion zurückgeben, aber der DI funktioniert für die Konstante nicht. Überprüfen Sie diese Geige, damit Sie sehen können, für welche Methoden DI funktioniert.

Wenn Sie also Ihre Frage beantworten, können Sie keine Konstante mit anderen Konstanten definieren.

Aber Sie können dies tun:

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;

  });

Überprüfen Sie diese Geige, um zu sehen, ob sie funktioniert:

Wenn Sie mehr über DI erfahren möchten, lesen Sie diesen Beitrag .

lao
quelle
147

Ein einfacher Weg, dies zu tun, ist folgender:

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

Und verwenden Sie die Konstanten wie folgt:

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

Credits: Link

Linkmichiel
quelle
3
@Helzgate Das hat @ gabn88 nicht gesagt. Die Funktion, an die übergeben wird, myApp.constantist ein sofort aufgerufener Funktionsausdruck (IIFE). Es nennt sich so, dass Sie nicht müssen! Es sieht so aus : (function (params) {//do stuff})(). Beachten Sie die Klammern um den Funktionsausdruck und den zusätzlichen Satz am Ende.
Daemonexmachina
@Helzgate Die Konstante mit dem Namen RESOURCESist daher kein Funktionsausdruck, sondern das von dieser Funktion zurückgegebene Objekt .
Daemonexmachina
2
Beste Antwort verfügbar.
Jelle Oosterbosch
2
Sollte ;nach dem zurückgegebenen Objekt kein Semikolon stehen, z. B.: return { ..... };Ich weiß, dass Sie technisch gesehen kein Semikolon benötigen, obwohl dies auf der automatischen Semikoloneinfügung von Javascript basiert, wie dieser Link - Aber was ist die beste Vorgehensweise?
Redfox05
RESOURCES().USERS_DOMAINLesen Sie zur besseren Übersicht die obigen Kommentare zum sofort aufgerufenen Funktionsausdruck (IIFE) , wenn Sie dies letztendlich tun müssen. Ich nehme an, das war der Kommentar von Helzgate, über den gelöscht wurde.
Redfox05
13

Ich mache das so:

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
quelle
@Beterraba. Könnten Sie das näher erläutern? Wohin würde dieser Code gehen? Vielen Dank. Mark
mark1234
@ mark1234 Dieser Code kann gehen, wohin Sie wollen. Ich möchte dies in meine Servicedatei aufnehmen. Sie müssen daran denken, das constantsModul in Ihr Hauptmodul aufzunehmen.
Beterraba
8

Solange Sie keinen Zugriff auf Ihre Konstante in Anbietern benötigen, sollte dies gut funktionieren:

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

Wenn Sie Zugriff auf Ihre Konstanten in Anbietern benötigen, müssen Sie wahrscheinlich noch etwas arbeiten:

.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) {
 })
Peter Rietzler
quelle
Diese Antwort sollte mehr Liebe bekommen :). Danke;)
Nicu Surdu
4

Ich kann nicht sicher sagen, ob das (im) möglich ist. Eine Problemumgehung wäre jedoch, die Basiskonstanten als reguläre Konstanten und die übergeordneten Konstanten als Dienste zu definieren, die Verschlüsse verwenden, um sicherzustellen, dass sie nicht geändert werden können.

Grobes Beispiel:

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

Und verwenden Sie es nach der Injektion des Dienstes:

MyServiceName.GET_SECOND_ORDER_CONST();

Es ist nicht sehr elegant, aber es sollte die Arbeit erledigen.

Thalis K.
quelle
3

Die von @Linkmichiel bereitgestellte Lösung ist gut, aber wenn Sie unbedingt eine Konstante in einer anderen verwenden möchten, können Sie sie im Konfigurationsblock kombinieren:

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>

Nach der Konfigurationsphase werden alle Konstanten korrekt eingerichtet (probieren Sie das Snippet aus).

Die Moral der Geschichte lautet: Angular ist so cool, dass Sie sogar die Konstanten ändern können.

fracz
quelle
1
Als Ergänzung. Sie müssen for (prop in RESOURCES) {mit var deklarieren oder lassen, wie for (let prop in RESOURCES) {.
Josivan