web-dev-qa-db-fra.com

Erreur DI angulaire - EXCEPTION: impossible de résoudre tous les paramètres

J'ai construit une application de base en Angular, mais j'ai rencontré un problème étrange qui empêchait d'injecter un service dans l'un de mes composants. Cependant, il s’injecte bien dans l’un des trois autres composants que j’ai créés.

Pour commencer, voici le service:

import { Injectable } from '@angular/core';

@Injectable()
export class MobileService {
  screenWidth: number;
  screenHeight: number;

  constructor() {
    this.screenWidth = window.outerWidth;
    this.screenHeight = window.outerHeight;

    window.addEventListener("resize", this.onWindowResize.bind(this) )
  }

  onWindowResize(ev: Event) {
    var win = (ev.currentTarget as Window);
    this.screenWidth = win.outerWidth;
    this.screenHeight = win.outerHeight;
  }

}

Et le composant avec lequel il refuse de travailler:

import { Component, } from '@angular/core';
import { NgClass } from '@angular/common';
import { ROUTER_DIRECTIVES } from '@angular/router';

import {MobileService} from '../';

@Component({
  moduleId: module.id,
  selector: 'pm-header',
  templateUrl: 'header.component.html',
  styleUrls: ['header.component.css'],
  directives: [ROUTER_DIRECTIVES, NgClass],
})
export class HeaderComponent {
  mobileNav: boolean = false;

  constructor(public ms: MobileService) {
    console.log(ms);
  }

}

L'erreur que je reçois dans la console du navigateur est la suivante:

EXCEPTION: Impossible de résoudre tous les paramètres pour HeaderComponent: (?).

J'ai le service dans la fonction d'amorçage afin qu'il ait un fournisseur. Et je semble être capable de l'injecter dans le constructeur de n'importe lequel de mes autres composants sans problème.

318
Keith Otto

Importez-le du fichier où il est déclaré directement au lieu du baril.

Je ne sais pas ce qui cause exactement le problème, mais je l'ai vu mentionné plusieurs fois (probablement une sorte de dépendance circulaire).

Il devrait également être réparable en modifiant l'ordre des exportations dans le baril (ne pas connaître les détails, mais a également été mentionné)

376
Günter Zöchbauer

En plus des réponses précédentes, il semble que cette erreur se produise également lorsque le service injectable manque le décorateur @Injectable(). Donc, avant de déboguer la dépendance cyclique et l'ordre de vos importations/exportations, effectuez une simple vérification pour savoir si votre service a bien défini @Injectable().

Ceci s’applique à la dernière version angulaire actuelle, Angular 2.1.0.

J'ai ouvert un numéro à ce sujet .

268
J.P. ten Berge

À partir de 2.2.3 angulaire, il existe maintenant une fonction utilitaire forwardRef() qui vous permet d’injecter des fournisseurs non encore définis.

Par non défini, je veux dire que la carte d'injection de dépendance ne connaît pas l'identifiant. C'est ce qui se passe lors des dépendances circulaires. Vous pouvez avoir des dépendances circulaires dans Angular qu'il est très difficile de démêler et de voir.

export class HeaderComponent {
  mobileNav: boolean = false;

  constructor(@Inject(forwardRef(() => MobileService)) public ms: MobileService) {
    console.log(ms);
  }

}

L'ajout de @Inject(forwardRef(() => MobileService)) au paramètre du constructeur dans le code source de la question d'origine résoudra le problème.

Références

Angular 2 Manual: ForwardRef

Références en Angular 2

93
cgTag

FAUX # 1: Oublier le décorateur:

//Uncaught Error: Can't resolve all parameters for MyFooService: (?).
export class MyFooService { ... }

WRONG # 2: Omettre le symbole "@":

//Uncaught Error: Can't resolve all parameters for MyFooService: (?).
Injectable()
export class MyFooService { ... }

WRONG # 3: Omettre les "()" symboles:

//Uncaught Error: Can't resolve all parameters for TypeDecorator: (?).
@Injectable
export class MyFooService { ... }

WRONG # 4: Minuscule "i":

//Uncaught ReferenceError: injectable is not defined
@injectable
export class MyFooService { ... }

WRONG # 5: Vous avez oublié: import {Injectable} à partir de '@ angular/core';

//Uncaught ReferenceError: Injectable is not defined
@Injectable
export class MyFooService { ... }

CORRECT:

@Injectable()
export class MyFooService { ... }
46
J.M.I. MADISON

Comme indiqué précédemment, le problème est dû à la commande d'exportation dans le baril, qui est provoquée par des dépendances circulaires.

Une explication plus détaillée est disponible ici: https://stackoverflow.com/a/37907696/893630

24
Michael

J'ai également rencontré cela en injectant le service A dans le service B et vice versa.

_ {Je pense que c’est une bonne chose que cela échoue rapidement car il devrait probablement être évité de toute façon}. Si vous souhaitez que vos services soient plus modulaires/réutilisables, évitez au maximum les références circulaires. This post met en évidence les pièges qui l’entourent. 

Par conséquent, j'ai les recommandations suivantes:

  • Si vous estimez que les classes interagissent trop souvent (je parle de envie des fonctionnalités ), vous pouvez envisager de fusionner les 2 services en 1 classe.
  • Si ce qui précède ne fonctionne pas pour vous, envisagez d'utiliser un 3ème service _ ((un EventService) que les deux services peuvent injecter pour échanger des messages.
17
Stephen Paul

Au profit des chercheurs; J'ai eu cette erreur. C'était simplement un symbole @ manquant.

C'est à dire. Cela produit l'erreur Can't resolve all parameters for MyHttpService.

Injectable()
export class MyHttpService{
}

L'ajout du symbole @ manquant le corrige.

@Injectable()
export class MyHttpService{
}
17
HockeyJ

Dans mon cas, je devais ajouter import "core-js/es7/reflect"; à mon application pour que @Injectable fonctionne.

8
AJ Richardson

Vous obtenez cette erreur si vous avez le service A qui dépend d'une propriété static/method du service B et que le service B lui-même dépend du service UNE injection de dépendance au trough. C'est donc une sorte de dépendance circulaire, bien que ce ne soit pas le cas puisque la propriété/méthode est statique. Probablement un bug qui se produit en combinaison avec AOT.

8
M K

En plus du décorateur @Injectable() manquant

Le décorateur manquant @Injectable() dans la classe abstraite a généré la résolution Impossible de résoudre tous les paramètres de service: (?) Le décorateur doit être présent dans MyService ainsi que dans la classe dérivée BaseService

//abstract class
@Injectable()
abstract class BaseService { ... }

//MyService    
@Injectable()
export class MyService extends BaseService {
.....
}
7
Bart

Dans mon cas, c'est arrivé parce que je n'ai pas déclaré le type d'un paramètre constructeur.

J'ai eu quelque chose comme ça:

constructor(private URL, private http: Http) { }

puis changer en le code ci-dessous a résolu mon problème.

constructor(private URL : string, private http: Http) {}
6
Alf Moh

Supprimer des paramètres de la méthode constructeur injectable () l’a résolu pour mon cas.

5
Matjaz Hirsman

pour moi, c'était simplement le manque de () dans @Injectable. Propre est @Injectable ()

5
repo

Dans mon cas, c’était à cause du plugin Augury, désactivez-le. L'option alternative est aot, fonctionne également.

tous les crédits à @ Boboss74, il a posté la réponse ici: https://github.com/angular/angular/issues/23958

4
Tinh Dang

Pour moi, cette erreur survient lorsque jea désactivé par erreurcette importation dans le fichier polyfills.ts.

/** Evergreen browsers require these. **/
// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
import 'core-js/es7/reflect';
2
Ahmed Elkoussy

Pour moi, le problème était encore plus énervant. J'utilisais un service dans un service et j'avais oublié de l'ajouter comme dépendance dans le module d'application!

2
Ophir Stern

Vous devez ajouter un tableau de fournisseurs dans @Component Decorator ou dans le module où votre composant est déclaré. Composant intérieur, vous pouvez faire comme ci-dessous:

@Component({
  moduleId: module.id,
  selector: 'pm-header',
  templateUrl: 'header.component.html',
  styleUrls: ['header.component.css'],
  directives: [ROUTER_DIRECTIVES, NgClass],
  providers: [MobileService]
})
2
Shivang Gupta

Dans mon cas, transmettre de mauvais paramètres au constructeur génère cette erreur. L'idée de base de cette erreur est que vous avez inconsciemment passé des arguments erronés à une fonction.

export class ProductComponent {
    productList: Array<Product>;

    constructor(productList:Product) { 
         // productList:Product this arg was causing error of unresolved parameters.
         this.productList = [];
    }
}

J'ai résolu ce problème en supprimant simplement cet argument.

2
Codiee

Une autre possibilité est de ne pas définir emitDecoratorMetadata sur true dans tsconfig.json

{
  "compilerOptions": {

     ...

    "emitDecoratorMetadata": true,

     ...

    }

}
2
Stewart_R

Bien que le ordering des classes exportées à partir de barils ait été mentionné, le scénario suivant peut également produire le même effet.

Supposons que les classes A, B et C soient exportées du même fichier où A dépend de B et C:

@Injectable()
export class A {
    /** dependencies injected */
    constructor(private b: B, private c: C) {}
}

@Injectable()
export class B {...}

@Injectable()
export class C {...}

Dans la mesure où Angular ne connaît pas encore les classes dépendante (c'est-à-dire, dans ce cas, les classes B et C), (probablement au moment de l'exécution pendant le processus d'injection de dépendance d'Angular sur la classe A

Solution

La solution consiste à déclarer et à exporter les classes dépendantes avant la classe où l'ID est effectué. 

c'est-à-dire que, dans le cas ci-dessus, la classe A est déclarée juste après que ses dépendances ont été définies: 

@Injectable()
export class B {...}

@Injectable()
export class C {...}

@Injectable()
export class A {
    /** dependencies injected */
    constructor(private b: B, private c: C) {}
}
1
Ahmad Baktash Hayeri

J'ai rencontré cette erreur en saisissant le nom du service, c'est-à-dire le constructeur (private myService: MyService ).

Pour les services mal orthographiés, j'ai pu déterminer quel service posait problème (plusieurs de ceux-ci étaient répertoriés dans le constructeur) en inspectant la page dans Chrome-> Console. Vous verrez dans le message une liste de tableaux "paramètres" en affichant objet Objet, objet Objet,? (ou quelque chose comme ça). Remarquez où le "?" est et c’est la position du service qui cause le problème. 

1
maleman

Dans mon cas, la raison était la suivante:

  • mon service injectable A étendu une autre classe B
  • B avait un constructeur qui nécessitait un argument
  • Je n'avais défini aucun constructeur dans A

En conséquence, lors de la tentative de création d'un objet A, le constructeur par défaut a échoué. Je ne sais pas pourquoi ce n'était pas une erreur de compilation.

Je l'ai résolu en ajoutant simplement un constructeur dans A, qui a correctement appelé le constructeur de B.

1
Vic Seedoubleyew

Dans mon cas, j'essayais d'étendre "NativeDateAdapter" afin de remplacer la méthode "format(date: Date, displayFormat: Object)". 

Dans AngularMaterial-2 DatePicker.

Donc, en gros, j'ai oublié d'ajouter @Injectable une annotation.

Après avoir ajouté ceci à ma classe "CustomDateAdapter":

@Injectable({
  providedIn: 'root'
})

L'erreur est partie.

1
Muhammed Ozdogan

Lors de l’utilisation d’importations en fûts, pensez d’abord à importer des produits injectables.

0
marekozw

Cette réponse pourrait être très utile pour résoudre ce problème. De plus, dans mon cas, l'exportation du service en tant que default en était la cause.

FAUX:

@Inject()
export default class MobileService { ... }

CORRECT:

@Inject()
export class MobileService { ... }
0
otiai10

Cela se produit parfois lorsque vous avez déclaré le module intégré d'Angular (HttpClientModule, HttpErrorResponse etc.) dans app.module.js. J'ai également fait face au même problème mais résolu maintenant.

L'erreur que j'ai faite a été de mentionner HttpClientModule dans Fournisseurs au lieu de Importer du module angulaire

0
ishu

Je t'ai eu!

Si aucune des réponses ci-dessus ne vous a aidé, vous pouvez peut-être importer un élément du même file lorsqu'un composant injecte le service.

J'explique mieux:

C'est le service file :

// your-service-file.ts
import { helloWorld } from 'your-component-file.ts'

@Injectable()
export class CustomService() {
  helloWorld()
}

C'est le composant fichier :

@Component({..})
export class CustomComponent {
  constructor(service: CustomService) { }
}

export function helloWorld() {
  console.log('hello world');
}

Cela pose donc des problèmes même si le symbole ne se trouve pas dans le même composant, mais dans le même fichier. Déplacez le symbole (cela peut être une fonction, une constante, une classe, etc.) ailleurs et l'erreur disparaîtra

0
Cristian Traìna

Pour moi, c'était parce que j'avais une ligne vide entre mon décorateur @Component et ma classe de composants. Cela a empêché le décorateur de s’appliquer à la classe.

0
fwip

Cela peut être un problème très difficile à résoudre en raison du manque de retour d'information sur l'erreur. Si vous êtes préoccupé par une dépendance cyclique réelle, voici la chose la plus importante à examiner dans la trace de pile: a) le nom du service b) le paramètre constructeur de ce service comportant un point d'interrogation, par exemple. si cela ressemble à ceci:

ne peut pas résoudre tous les paramètres pour AuthService: ([objet Object], [objet Object], [objet Object], [objet Object],?)

cela signifie alors que le cinquième paramètre est un service qui dépend également d'AuthService. c'est-à-dire un point d'interrogation, cela signifie qu'il n'a pas été résolu par DI.

A partir de là, il vous suffit de découpler les 2 services en restructurant le code.

0
sarora

Dans mon cas, j'exportais une classe et une énumération à partir du même fichier de composant:

mComponent.component.ts:

export class MyComponentClass{...}
export enum MyEnum{...}

Ensuite, j'essayais d'utiliser MyEnum à partir d'un enfant de MyComponentClass. Cela causait le Impossible de résoudre tous les paramètres .

En déplaçant MyEnum dans un dossier distinct de MyComponentClass, cela a résolu mon problème!

Comme Günter Zöchbauer l'a mentionné, cela se produit car un service ou un composant est dépendant de manière circulaire.

0

Cela se produit également lorsque vous faites référence à une variable interface.

Changer interface pour class l'a corrigé, en travaillant avec et sans @Inject.

0
zurfyx

Si votre service est défini dans le même fichier qu'un composant (qui le consomme) et que le service est défini après le composant du fichier, vous risquez d'obtenir cette erreur. Ceci est dû au même problème de "forwardRef" que d'autres ont mentionné. En ce moment, VSCode n'aime pas trop vous montrer cette erreur et la compilation est compilée avec succès.

L'exécution de la construction avec --aot peut masquer ce problème en raison du fonctionnement du compilateur (probablement lié à la secousse de l'arbre). 

Solution: Assurez-vous que le service est défini dans un autre fichier ou avant la définition du composant. (Je ne suis pas sûr si forwardRef peut être utilisé dans ce cas, mais cela semble maladroit de le faire).

Si j'ai un service très simple qui est très fortement lié à un composant (un peu comme un modèle de vue) - par exemple. ImageCarouselComponent, je peux le nommer ImageCarouselComponent.service.ts afin que tout ne soit pas mélangé avec mes autres services.

0
Simon_Weaver

Dans mon cas, il s’agissait d’une référence circulaire .

Pas bon :(

0
lucbonnin

Pour moi, c’est parce que j’ai arrêté d’utiliser le drapeau -aot en essayant d’accélérer la compilation.

 ng serve -aot
0
B Jarmain

Dans mon cas, j'ai pris une dépendance sur un service qui n'avait aucune dépendance et, par conséquent, je n'ai pas ajouté de fonction constructor() à la classe de service. J'ai ajouté un constructeur sans paramètre à la classe de service dépendante et tout a commencé à fonctionner.

0
Hallmanac