Service d’injection dans app.config

Je veux injecter un service dans app.config, afin que les données puissent être récupérées avant l’appel du contrôleur. Je l’ai essayé comme ceci:

Un service:

app.service('dbService', function() { return { getData: function($q, $http) { var defer = $q.defer(); $http.get('db.php/score/getData').success(function(data) { defer.resolve(data); }); return defer.promise; } }; }); 

Config:

 app.config(function ($routeProvider, dbService) { $routeProvider .when('/', { templateUrl: "partials/editor.html", controller: "AppCtrl", resolve: { data: dbService.getData(), } }) }); 

Mais j’ai cette erreur:

Erreur: Fournisseur inconnu: dbService à partir de EditorApp

Comment corriger la configuration et injecter ce service?

Alex a donné la bonne raison de ne pas pouvoir faire ce que vous essayez de faire, donc +1. Mais vous rencontrez ce problème parce que vous n’utilisez pas tout à fait la façon dont ils sont conçus.

resolve prend soit la chaîne d’un service, soit une fonction renvoyant une valeur à injecter. Comme vous faites ce dernier, vous devez transmettre une fonction réelle:

 resolve: { data: function (dbService) { return dbService.getData(); } } 

Lorsque le framework va résoudre des data , il va injecter le dbService dans la fonction afin de pouvoir l’utiliser librement. Vous n’avez pas besoin d’injecter dans le bloc de config du tout pour y parvenir.

Bon appétit!

Configurez votre service en tant que fournisseur AngularJS personnalisé

En dépit de la réponse acceptée, vous pouvez en fait faire ce que vous avez l’intention de faire, mais vous devez le configurer en tant que fournisseur configurable pour qu’il soit disponible en tant que service pendant la phase de configuration. fournisseur comme indiqué ci-dessous. La principale différence réside dans le fait qu’après avoir défini la valeur de defer , vous définissez la propriété defer.promise sur l’object promis renvoyé par $http.get :

Service fournisseur: (fournisseur: recette de service)

 app.provider('dbService', function dbServiceProvider() { //the provider recipe for services require you specify a $get function this.$get= ['dbhost',function dbServiceFactory(dbhost){ // return the factory as a provider // that is available during the configuration phase return new DbService(dbhost); }] }); function DbService(dbhost){ var status; this.setUrl = function(url){ dbhost = url; } this.getData = function($http) { return $http.get(dbhost+'db.php/score/getData') .success(function(data){ // handle any special stuff here, I would suggest the following: status = 'ok'; status.data = data; }) .error(function(message){ status = 'error'; status.message = message; }) .then(function(){ // now we return an object with data or information about error // for special handling inside your application configuration return status; }) } } 

Maintenant, vous avez un fournisseur personnalisé configurable, il vous suffit de l’injecter. La principale différence réside dans l’absence du “fournisseur sur votre injectable”.

config:

 app.config(function ($routeProvider) { $routeProvider .when('/', { templateUrl: "partials/editor.html", controller: "AppCtrl", resolve: { dbData: function(DbService, $http) { /* *dbServiceProvider returns a dbService instance to your app whenever * needed, and this instance is setup internally with a promise, * so you don't need to worry about $q and all that */ return DbService('http://dbhost.com').getData(); } } }) }); 

utiliser des données résolues dans votre appCtrl

 app.controller('appCtrl',function(dbData, DbService){ $scope.dbData = dbData; // You can also create and use another instance of the dbService here... // to do whatever you programmed it to do, by adding functions inside the // constructor DbService(), the following assumes you added // a rmUser(userObj) function in the factory $scope.removeDbUser = function(user){ DbService.rmUser(user); } }) 

Alternatives possibles

L’alternative suivante est une approche similaire, mais permet à la définition de se produire dans le .config , en encapsulant le service dans le module spécifique dans le contexte de votre application. Choisissez la méthode qui vous convient. Voir également ci-dessous des notes sur une troisième alternative et des liens utiles pour vous aider à maîsortingser toutes ces choses

 app.config(function($routeProvider, $provide) { $provide.service('dbService',function(){}) //set up your service inside the module's config. $routeProvider .when('/', { templateUrl: "partials/editor.html", controller: "AppCtrl", resolve: { data: } }) }); 

Quelques ressources utiles

  • John Lindquist a une excellente explication de 5 minutes et une démonstration à egghead.io , et c’est l’une des leçons gratuites! J’ai fondamentalement modifié sa démonstration en la rendant $http spécifique dans le contexte de cette requête
  • Voir le guide du développeur AngularJS sur les fournisseurs
  • Il y a aussi une excellente explication sur l’ factory / le service / le provider à clevertech.biz .

Le fournisseur vous donne un peu plus de configuration sur la méthode .service , ce qui le rend meilleur en tant que fournisseur de niveau application, mais vous pouvez également encapsuler cela dans l’object config lui-même en injectant $provide dans config comme ceci:

Réponse courte: vous ne pouvez pas. AngularJS ne vous permettra pas d’injecter des services dans la configuration car il ne peut pas être sûr qu’ils ont été chargés correctement.

Voir cette question et réponse: dependency injection AngularJS de value dans module.config

Un module est une collection de blocs de configuration et d’exécution qui sont appliqués à l’application pendant le processus de démarrage. Dans sa forme la plus simple, le module consiste en une collection de deux types de blocs:

Blocs de configuration – exécutés lors des phases d’enregistrement et de configuration du fournisseur. Seuls les fournisseurs et les constantes peuvent être injectés dans les blocs de configuration. Cela permet d’éviter une instanciation accidentelle de services avant qu’ils ne soient entièrement configurés.

Je ne pense pas que vous êtes censé être capable de faire cela, mais j’ai réussi à injecter un service dans un bloc de config . (AngularJS v1.0.7)

 angular.module('dogmaService', []) .factory('dogmaCacheBuster', [ function() { return function(path) { return path + '?_=' + Date.now(); }; } ]); angular.module('touch', [ 'dogmaForm', 'dogmaValidate', 'dogmaPresentation', 'dogmaController', 'dogmaService', ]) .config([ '$routeProvider', 'dogmaCacheBusterProvider', function($routeProvider, cacheBuster) { var bust = cacheBuster.$get[0](); $routeProvider .when('/', { templateUrl: bust('touch/customer'), controller: 'CustomerCtrl' }) .when('/screen2', { templateUrl: bust('touch/screen2'), controller: 'Screen2Ctrl' }) .otherwise({ redirectTo: bust('/') }); } ]); angular.module('dogmaController', []) .controller('CustomerCtrl', [ '$scope', '$http', '$location', 'dogmaCacheBuster', function($scope, $http, $location, cacheBuster) { $scope.submit = function() { $.ajax({ url: cacheBuster('/customers'), //server script to process data type: 'POST', //Ajax events // Form data data: formData, //Options to tell JQuery not to process data or worry about content-type cache: false, contentType: false, processData: false, success: function() { $location .path('/screen2'); $scope.$$phase || $scope.$apply(); } }); }; } ]); 

** Demander explicitement des services à d’autres modules en utilisant angular.injector **

Juste pour élaborer sur la réponse de Kim3er , vous pouvez fournir des services, des usines, etc. sans les changer en fournisseurs, à condition qu’ils soient inclus dans d’autres modules …

Cependant, je ne suis pas sûr que le *Provider (qui est créé en interne par angular après avoir traité un service ou une usine) sera toujours disponible (cela peut dépendre de ce qui a été chargé en premier), car les modules de chargement angular se chargent lentement.

Notez que si vous souhaitez réinjecter les valeurs, elles doivent être traitées comme des constantes.

Voici un moyen plus explicite et probablement plus fiable de le faire

 var base = angular.module('myAppBaseModule', []) base.factory('Foo', function() { console.log("Foo"); var Foo = function(name) { this.name = name; }; Foo.prototype.hello = function() { return "Hello from factory instance " + this.name; } return Foo; }) base.service('serviceFoo', function() { this.hello = function() { return "Service says hello"; } return this; }); var app = angular.module('appModule', []); app.config(function($provide) { var base = angular.injector(['myAppBaseModule']); $provide.constant('Foo', base.get('Foo')); $provide.constant('serviceFoo', base.get('serviceFoo')); }); app.controller('appCtrl', function($scope, Foo, serviceFoo) { $scope.appHello = (new Foo("app")).hello(); $scope.serviceHello = serviceFoo.hello(); }); 

Vous pouvez utiliser le service $ inject pour injecter un service dans votre configuration

 app.config (fonction ($ offrant) {

     $ provide.decorator ("$ exceptionHandler", fonction ($ delegate, $ injector) {
         fonction de retour (exception, cause) {
             var $ rootScope = $ injector.get ("$ rootScope");
             $ rootScope.addError ({message: "Exception", raison: exception});
             $ delegate (exception, cause);
         };
     })

 })

Source: http://odetocode.com/blogs/scott/archive/2014/04/21/better-error-handling-in-angularjs.aspx

Utiliser $ injector pour appeler des méthodes de service dans config

J’ai eu un problème similaire et j’ai résolu le problème en utilisant le service $ injector comme indiqué ci-dessus. J’ai essayé d’injecter directement le service mais j’ai fini par avoir une dépendance circulaire sur $ http. Le service affiche un modal avec l’erreur et j’utilise le modal ui-bootstrap qui a également une dépendance sur $ https.

  $httpProvider.interceptors.push(function($injector) { return { "responseError": function(response) { console.log("Error Response status: " + response.status); if (response.status === 0) { var myService= $injector.get("myService"); myService.showError("An unexpected error occurred. Please refresh the page.") } } } 

Une solution très facile à faire

Remarque : c’est uniquement pour un appel asynchrone, car le service n’est pas initialisé lors de l’exécution de la configuration.

Vous pouvez utiliser la méthode run() . Exemple :

  1. Votre service s’appelle “MyService”
  2. Vous voulez l’utiliser pour une exécution asynchrone sur un fournisseur “MyProvider”

Votre code :

 (function () { //To isolate code TO NEVER HAVE A GLOBAL VARIABLE! //Store your service into an internal variable //It's an internal variable because you have wrapped this code with a (function () { --- })(); var theServiceToInject = null; //Declare your application var myApp = angular.module("MyApplication", []); //Set configuration myApp.config(['MyProvider', function (MyProvider) { MyProvider.callMyMethod(function () { theServiceToInject.methodOnService(); }); }]); //When application is initialized inject your service myApp.run(['MyService', function (MyService) { theServiceToInject = MyService; }]); }); 

Le plus simple: $injector = angular.element(document.body).injector()

Puis utilisez cela pour lancer invoke() ou get()

Eh bien, j’ai eu un peu de mal avec celui-ci, mais je l’ai effectivement fait.

Je ne sais pas si les réponses sont obsolètes à cause de changements dans les angles, mais vous pouvez le faire de cette façon:

Ceci est votre service:

 .factory('beerResortingevalService', function ($http, $q, $log) { return { getRandomBeer: function() { var deferred = $q.defer(); var beer = {}; $http.post('beer-detail', {}) .then(function(response) { beer.beerDetail = response.data; }, function(err) { $log.error('Error getting random beer', err); deferred.reject({}); }); return deferred.promise; } }; }); 

Et c’est la config

 .when('/beer-detail', { templateUrl : '/beer-detail', controller : 'productDetailController', resolve: { beer: function(beerResortingevalService) { return beerResortingevalService.getRandomBeer(); } } })