web-dev-qa-db-fra.com

utiliser $ http dans un fournisseur personnalisé dans app config, angular.js

La question principale - est-ce possible? J'ai essayé sans chance ..

app.js principale

...
var app = angular.module('myApp', ['services']);
app.config(['customProvider', function (customProvider) {

}]);
...

fournisseur lui-même

var services = angular.module('services', []);
services.provider('custom', function ($http) {
});

Et j'ai une telle erreur:

Uncaught Error: Unknown provider: $http from services 

Des idées?

Merci!

90
Kosmetika

La ligne de fond est:

  • Vous [~ # ~] ne pouvez pas [~ # ~] injecter un service dans la section de configuration du fournisseur.
  • Vous [~ # ~] pouvez [~ # ~] injecter un service dans la section qui initialise le service du fournisseur.

Détails:

Le framework angulaire a un processus d’initialisation en 2 phases:

PHASE 1: Config

Au cours de la phase config, tous les fournisseurs sont initialisés et toutes les sections config sont exécutées. Les sections config peuvent contenir du code qui configure les objets fournisseur et peuvent donc être injectées avec des objets fournisseur. Cependant, étant donné que les fournisseurs sont les fabriques pour les objets de service et que, à ce stade, les fournisseurs ne sont pas complètement initialisés/configurés -> vous ne pouvez pas demander au fournisseur de créer un service pour vous à ce stade -> à l'étape de configuration vous ne pouvez pas utiliser/injecter des services. Lorsque cette phase est terminée, tous les fournisseurs sont prêts (plus aucune configuration de fournisseur ne peut être effectuée une fois la phase de configuration terminée).

PHASE 2: Run

Pendant la phase run, toutes les sections run sont exécutées. A ce stade les fournisseurs sont prêts et peuvent créer des services -> pendant la phase run, vous pouvez utiliser/injecter des services.

Exemples:

1. Injecter le $http service à la fonction d’initialisation du fournisseur NE FONCTIONNERA PAS

//ERRONEOUS
angular.module('myModule').provider('myProvider', function($http) {
    // SECTION 1: code to initialize/configure the PROVIDER goes here (executed during `config` phase)
    ...

    this.$get = function() {
        // code to initialize/configure the SERVICE goes here (executed during `run` stage)

        return myService;
    };
});

Puisque nous essayons d’injecter le $http service dans une fonction qui est exécutée pendant la phase config nous obtiendrons une erreur:

Uncaught Error: Unknown provider: $http from services 

Ce que cette erreur dit réellement, c’est que le $httpProvider qui sert à créer le $http Le service n’est pas encore prêt (puisque nous sommes toujours dans la phase config.).

2. Injecter le $http service à la fonction d’initialisation du service [~ # ~] va [~ # ~] fonctionner:

//OK
angular.module('myModule').provider('myProvider', function() {
    // SECTION 1: code to initialize/configure the PROVIDER goes here (executed during `config` phase)
    ...

    this.$get = function($http) {
        // code to initialize/configure the SERVICE goes here (executed during `run` stage)

        return myService;
    };
});

Puisque nous injectons maintenant le service dans la fonction d'initialisation du service, qui est exécutée pendant la phase run, ce code fonctionnera.

158
Dana Shalev

Cela pourrait vous donner un peu de poids:

var initInjector = angular.injector(['ng']);
var $http = initInjector.get('$http');

Mais soyez prudent, les rappels de succès/d'erreur peuvent vous maintenir dans une situation de concurrence critique entre le démarrage de l'application et la réponse du serveur.

63
Cody

C'est une vieille question, il semble que nous ayons un problème avec les œufs de poule si nous voulons nous appuyer sur la capacité principale de la bibliothèque.

Au lieu de résoudre le problème de manière fondamentale, ce que j'ai fait est de passer outre. Créez une directive qui enveloppe tout le corps. Ex.

<body ng-app="app">
  <div mc-body>
    Hello World
  </div>
</body>

Maintenant mc-body Doit être initialisé avant le rendu (une fois), ex.

link: function(scope, element, attrs) {
  Auth.login().then() ...
}

Auth est un service ou un fournisseur, ex.

.provider('Auth', function() {
  ... keep your auth configurations
  return {
    $get: function($http) {
      return {
        login: function() {
          ... do something about the http
        }
      }
    }
  }
})

Il me semble que j’ai le contrôle de l’ordre du bootstrap, c’est après que le bootstrap normal résolve toute la configuration du fournisseur, puis tente d’initialiser la directive mc-body.

Et cette directive me semble être en avance sur le routage, car le routage est également injecté via une directive ex. <ui-route />. Mais je peux me tromper à ce sujet. A besoin de plus d'enquête.

1
windmaomao