2016-01-12 1 views
4

J'ai un service angulaire comme ceci:Est-ce que le service Angulaire est vraiment singleton?

angular.module('MyModule') 
    .factory('SharedData', function(){ 
     return { 
      session_id: undefined, 
      getSessionId: function() { 
       return this.session_id; 
      }, 
      setSessionId: function (new_id) { 
       this.session_id = new_id; 
      }, 
     }; 
    }). 
    controller('MyController', ['SharedData', function(SharedData){ 
      console.log("Retrieved session id = " + SharedData.getSessionId()); 
       // getting undefined here! 
    }]); 

j'ai appelé le service à un moment plus tôt dans un autre module comme celui-ci:

angular.module('bootstrapper') 
    factory("AnotherService", function(){ 
      var injector = angular.injector(['MyModule', 'ng']), 
       shared_data = injector.get('SharedData'); 
       shared_data.setSessionId(getUrlParameter('SESSIONID')); 
      ... 

}); 

Le résultat de sortie de la console est définie.

Je pense que le SharedData dans 'MyController' et le SharedData dans 'AnotherService' ne sont pas le même objet. Cependant, les gens disent tous que les services angulaires sont des singletons. Sont-ils de vrais singletons? sur mes modules


Plus de détails: J'utilise le module 'bootstrapper' pour amorcer manuellement l'autre module 'MyModule':

angular.module('bootstrapper') 
    .run(function() { 
     angular.bootstrap(document, ['MyModule']); 
    }); 
+2

Oui, ils sont différents dans votre cas. Les services sont des singletons dans la ** même ** application. Ce n'est pas ton cas. – dfsq

+0

@dfsq Voulez-vous dire module quand vous avez dit 'application'? – gm2008

+1

Pas vraiment un module. L'application est ce que bootstrapped comme l'application. Il peut être 'ngApp' ou manuel' angular.bootstrap'. On dirait que vous avez deux applications? – dfsq

Répondre

1

Vous pouvez fournir des constantes à l'application au moment de l'amorçage en tant que dépendance de module. Pour plus d'informations, voir AngularJS $provide Service API Reference -- constant.

Mise à jour

Vous pouvez également ignorer l'application bootstrap et utiliser un bloc de configuration dans l'application MyModule.

angular.module('MyModule') 
    .config(function ($provide) { 
     $provide.constant("SESSIONID", getUrlParameter('SESSIONID')); 
}); 

Pour plus d'informations, voir le AngularJS angular.module API Reference,

+0

Sera-t-il possible de fournir l'ensemble du service à 'MyModule' de la même manière? Merci. – gm2008

+0

Oui, mais c'est mieux de le faire dans un bloc de configuration de l'application 'MyModule'. Voir la mise à jour de ma réponse. – georgeawg

+0

Merci pour la réponse. Cela a résolu mon problème. – gm2008

2

angular.factory ne sont pas des constructeurs, il me semble que l'utilisation de la place angular.service résoudrait votre problème,

+0

Le code d'origine était correct, votre version de fermeture est maladroite et ne devrait pas être utilisée. Le service et l'usine sont la même chose en ce qui concerne ce contexte. Donc, ça ne peut pas être le problème. – dfsq

+0

désolé pour la question @dfsq, quelle partie est maladroite? par curiosité – koox00

+0

@dfsq J'ai supprimé la partie nuisible de ma réponse, j'avais tort, merci pour vos commentaires. – axelduch

0

Après avoir réfléchi un peu, je pense que vous avez choisi de ne pas très bonne approche. Il est préférable de définir l'application bootstrapper et d'initialiser le service sharedData, puis de le partager avec d'autres modules dépendants. Remarque, pas applications comme dans votre cas, mais modules dépendants. Ce serait beaucoup plus simple et plus propre.

Voici un exemple de configuration qui permettrait bien "modularisation":

/** 
 
* Bootstrapper application. 
 
*/ 
 
angular.module('bootstrapper', ['dashboard']) 
 
    .factory('sharedData', function() { 
 
     return { 
 
      sessionId: undefined, 
 
      setSessionId: function(value) { 
 
       this.sessionId = value; 
 
      }, 
 
      getSessionId: function() { 
 
       return this.sessionId; 
 
      } 
 
     } 
 
    }) 
 
    .controller('BootController', function(sharedData) { 
 
     this.name = 'Bootstrapper app'; 
 
     sharedData.setSessionId('34sd-3sdf345g-23a2421b'); 
 
    }); 
 
    
 
/** 
 
* Apllication kicked off by main bootstrapper. 
 
*/ 
 
angular.module('dashboard', []) 
 
    .directive('dashboardModule', function() { 
 
     return { 
 
      controller: 'DashboardController as dashboard', 
 
      template: 
 
       "<div>" + 
 
       " {{ dashboard.name }} sessionId: {{ dashboard.sharedData.sessionId }}" + 
 
       "</div>" 
 
     }; 
 
    }) 
 
    .controller('DashboardController', function(sharedData) { 
 
     this.name = 'Dashboard'; 
 
     this.sharedData = sharedData; 
 
    });
<script src="https://code.angularjs.org/1.4.8/angular.js"></script> 
 

 
<body ng-app="bootstrapper" ng-controller="BootController as boot"> 
 
    
 
    <h3>{{ boot.name }}</h3> 
 
    
 
    <dashboard-module name="dashboard"></dashboard-module> 
 
    
 
    <!-- <some-other-module></some-other-module> --> 
 
    
 
</body>

+0

Merci d'avoir écrit la solution détaillée. Cependant, cela ne passe pas les données entre les applications. Je dois amorcer manuellement l'application principale parce que je dois d'abord récupérer des informations de configuration du serveur, puis configurer l'application principale en fonction de cette information. – gm2008