EXCEPTION: impossible de résoudre tous les paramètres

431

J'ai créé une application de base dans Angular 2, mais j'ai rencontré un problème étrange où je ne peux pas injecter de service dans l'un de mes composants. Cependant, il 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 j'obtiens dans la console du navigateur est la suivante:

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

J'ai le service dans la fonction bootstrap donc il a un fournisseur. Et je semble pouvoir l'injecter dans le constructeur de n'importe lequel de mes autres composants sans problème.

Keith Otto
la source
14
Peut-être l'importation? Est '../'un index.ts(baril)? Pouvez-vous essayer de l'importer à partir du fichier où il est déclaré directement à la place?
Günter Zöchbauer
Miraculeusement, cela semble l'avoir corrigé! Bizarre que cela ne fonctionnerait pas en utilisant le baril lorsque les autres composants avec lesquels j'ai testé le service l'ont fait. Si vous souhaitez publier cela comme une réponse au lieu d'un commentaire, je l'accepterai.
Keith Otto
11
Généralement une dépendance circulaire.
Gary
J'ai également eu ce problème avec la dépendance circulaire. Il vaut la peine de noter que les nouvelles versions du pack Web sont bien meilleures pour vous le dire
Enn
On dirait une dépendance circulaire, si vous utilisez angulaire> = 4 pour vous débarrasser de intex.ts (baril) et importer directement tout ce dont vous avez besoin.
Rammgarot

Réponses:

457

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 (je ne sais pas les détails, mais a également été mentionné)

Günter Zöchbauer
la source
16
c'est correct si vous avez par exemple un service injecté dans un autre service dont le premier doit venir en premier dans le baril.
Joao Garin
17
L'équipe Angular2 ne recommande plus les barils en raison de nombreux problèmes de ce type. Heureux d'entendre que je pourrais aider :)
Günter Zöchbauer
13
Je ne savais pas que l'équipe Angular 2 ne recommande pas de barils. Dans l'affirmative, ils devraient le noter dans le glossaire qui traite de leurs avantages. Et les projets comme angular2-webpack-starter ne devraient pas les utiliser.
Blue
3
Il semble que cela a été corrigé (ce n'est pas un problème 2.0.2). Je trouve les barils toujours utiles, surtout lorsque j'ai besoin d'importer plusieurs modèles et services entre différents modules. Ce import { cleanValues, getState, FirebaseService, NotificationService, ... } from '../../shared/services';fut une douleur quand cela n'a pas fonctionné (; NgModulen'aide pas avec les services singleton ...
Sasxa
3
Argghh je l'ai résolu en changeant l'ordre des exportations dans le fichier baril (index.ts) .. merci beaucoup
Spock
331

En plus des réponses précédentes données, il semble que cette erreur soit également lancée lorsque votre service injectable manque le @Injectable()décorateur réel . Donc, avant de déboguer la dépendance cyclique et l'ordre de vos importations / exportations, vérifiez simplement si votre service a réellement@Injectable() défini.

Cela s'applique à la dernière version angulaire actuelle, Angular 2.1.0.

J'ai ouvert un dossier à ce sujet .

JP ten Berge
la source
Oui, cette erreur est généralement due au fait que vous avez oublié d'ajouter @Injectable et que, par exemple, vous pouvez simplement importer le Routerdepuis '@ angular / router' et sans cet injectable, cette erreur se produira toujours (dès que vous décidez de créer une ligne de utiliser le code du routeur injecté.
Eric Bishard
Réponse impressionnante, mon problème était que j'ai ajouté une méthode à mon service et que je n'ai pas ajouté de point-virgule après l'accolade finale. Je ne sais pas pourquoi il doit en être ainsi, mais ce n'est pas le cas dans les classes de composants ... pour l'instant, je suis heureux de passer à autre chose!
egimaben
J'avais un modèle simple qui m'a donné cette erreur. J'ai utilisé le raccourci où vous créez vos propriétés dans le constructeur du modèle. Les types de propriétés étaient uniquement string et int. Puis soudain, ce problème a commencé à se produire. L'ajout de @Injectable () a résolu le problème. Bizarre car aucun de mes autres modèles n'a ajouté Injectable. Je dois ajouter que j'ai mis à jour pas mal de bibliothèques avant d'ajouter ce nouveau modèle. Peut-être avait quelque chose à voir avec ça, mais ça marche maintenant. Merci.
Moutono
@Moutono Correct. Avec un constructeur vide dans votre service, l'injection de dépendance ne semble pas être déclenchée et @injectable()n'est pas requise. Ce qui est une autre bizarrerie sur lui-même. Pour faire bonne mesure, je l'ajouterais quand même, simplement pour quand vous devriez décider d'injecter quelque chose.
JP ten Berge
Gardez à l'esprit que si votre service a une classe de base qui doit également être décorée avec @Injectable ()
Sam Shiles
110

Depuis Angular, 2.2.3il existe désormais une forwardRef()fonction utilitaire qui vous permet d'injecter des fournisseurs qui n'ont pas encore été définis.

Par non défini, je veux dire que la carte d'injection de dépendances 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 qui sont très difficiles à démêler et à voir.

export class HeaderComponent {
  mobileNav: boolean = false;

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

}

L'ajout @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

Manuel Angular 2: ForwardRef

Références directes dans Angular 2

Reactgular
la source
3
forwardRef()était déjà là en alpha ;-) Il n'est nécessaire que si le Mobileservice est déclaré plus bas dans le même fichier. Si les classes sont dans des fichiers différents, il n'est pas nécessaire deforwardRef()
Günter Zöchbauer
4
Günter Zöchbauer, j'essaie toujours de comprendre le vrai problème avec mon code, mais en attendant forwardRef()cela a aidé à se débarrasser du Can't resolve all parameters for ...message. Au moins, le composant fonctionne pendant que je cherche une meilleure solution au problème. (Et oui, la dépendance défaillante est importée directement de son fichier)
Nik
4
@ GünterZöchbauer J'ai mis à jour ma réponse avec des références. Je n'essaie pas de retirer de votre réponse, mais cela résout en fait le problème et les gens doivent le savoir. Si vous recherchez sur Google la question, aucun résultat ne dit d'utiliser forwardRef. C'est très difficile à trouver. Hier, il m'a fallu toute la journée pour résoudre ce problème.
Reactgular
Bizarre. J'ai posté au moins une douzaine de réponses qui suggèrent de m'utiliser foreardRefmoi-même mais pas plus après l' NgModuleintroduction. Je ne suis pas inquiet de perdre des représentants. Je suis juste curieux de savoir pourquoi vous rencontrez cela après que cela ne soit plus apparu depuis quelques mois. J'y regarderai de plus près quand je serai de retour dans quelques jours. Merci beaucoup pour la rétroaction.
Günter Zöchbauer
2
Si quelqu'un s'est également perdu au sujet des importations: importez {Component, Inject, ForwardRefFn, forwardRef} de '@ angular / core';
Natanael
69

FAUX # 1: Oubliant le décorateur:

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

FAUX # 2: Omission du symbole "@":

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

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

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

FAUX # 4: "i" minuscule:

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

FAUX # 5: Vous avez oublié: importez {Injectable} de '@ angular / core';

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

CORRECT:

@Injectable()
export class MyFooService { ... }
JMI MADISON
la source
27

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

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

Michael
la source
3
La commande n'a pas résolu mon problème. Ne pas utiliser le canon.
Michael Laffargue
21

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 et réutilisables, il est préférable d'éviter autant que possible les références circulaires. Ce post met en évidence les pièges qui l'entourent.

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

  • Si vous pensez que les classes interagissent trop souvent (je parle d' envie de fonctionnalités ), vous voudrez peut-être 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 , (an EventService) que les deux services peuvent injecter afin d'échanger des messages.
Stephen Paul
la source
1
C'est définitivement ce qui m'est arrivé, et c'est la voie à suivre. Si vous savez que plusieurs services nécessitent des mises à jour, utilisez un EventService. Il est plus extensible car vous devrez sans aucun doute exploiter ces événements lorsque vous étendez l'application en fonction de ces événements.
themightybun
17

Pour le bénéfice des chercheurs; J'ai eu cette erreur. C'était simplement un symbole @ manquant.

C'est à dire cela produit l' Can't resolve all parameters for MyHttpServiceerreur.

Injectable()
export class MyHttpService{
}

L'ajout du @symbole manquant le corrige.

@Injectable()
export class MyHttpService{
}
HockeyJ
la source
2
Dans mon cas, j'avais ajouté des classes et des interfaces supplémentaires entre @Injectable et la définition de classe de service, de sorte que la classe de service n'était plus marquée comme injectable.
Herc
Si vous oubliez complètement le décorateur @Injectable () sur une classe de service qui consomme d'autres services injectables, votre service mal décoré lèvera également cette erreur.
I. Buchan,
10

Dans mon cas, je devais ajouter import "core-js/es7/reflect";à ma demande pour faire du @Injectabletravail.

AJ Richardson
la source
9

Une autre possibilité est de ne pas avoir emitDecoratorMetadatadéfini la valeur true dans tsconfig.json

{
  "compilerOptions": {

     ...

    "emitDecoratorMetadata": true,

     ...

    }

}
Stewart_R
la source
8

Vous obtenez cette erreur si vous disposez du service A qui dépend d'une propriété / méthode statique du service B et que le service B lui-même dépend de l' injection de dépendances par le service A. C'est donc une sorte de dépendance circulaire, même si ce n'est pas le cas puisque la propriété / méthode est statique. Probablement un bogue qui se produit en combinaison avec AOT .

MK
la source
Je l'ai également eu quand il y a une dépendance à une fonction simplement définie dans le même fichier. Le diviser en un fichier séparé l'a corrigé.
Joe
1
Merci de l'avoir mentionné. Je me suis retrouvé dans la situation exacte. Je n'avais pas réalisé que l'accès direct aux classes statiques pouvait avoir quelque chose à voir avec la DI. J'avais ce schéma: A -> Bet les deux utilisaient la même classe statique. La solution avec forwardRefaide, mais je vais voir comment cela pourrait être démêlé. J'essaierai probablement de faire un vrai service à partir de cette classe statique (cela conduira également à une meilleure conception).
Slava Fomin II du
8

En plus du @Injectable()décorateur manquant

Le @Injectable()décorateur manquant dans la classe abstraite a produit Impossible de résoudre tous les paramètres de service: (?) Le décorateur doit être présent MyServicedans la classe dérivéeBaseService

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

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

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

J'avais quelque chose comme ça:

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

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

constructor(private URL : string, private http: Http) {}
Alf Moh
la source
5

pour moi, c'était juste un manque de ()@Injectable. Le bon est @Injectable ()

repo
la source
Ou dans mon cas, en supprimant accidentellement le @
TDP
4

La suppression des paramètres de la méthode constructor () injectable l'a résolu pour mon cas.

Matjaz Hirsman
la source
C'était exactement mon problème aussi. Je suis venu le poster mais je l'ai trouvé en premier! +1
aesede
alors comment envoyer les paramètres au service réutilisable?
3gwebtrain
2

Eh bien, pour moi, le problème était encore plus ennuyeux, j'utilisais un service au sein d'un service et j'ai oublié de l'ajouter comme dépendance dans l'appModule! J'espère que cela permet à quelqu'un d'économiser plusieurs heures en cassant l'application uniquement pour la reconstituer

Ophir Stern
la source
1
Je manquais juste une @Injectannotation. J'écartais exactement ce que dit le message d'erreur. Si vous ne soupçonnez pas de dépendances circulaires, accédez simplement à la classe mentionnée dans l'erreur et examinez tous les paramètres du constructeur et tous les membres de classe annotés @Injectet assurez-vous que vous faites bien DI sur chacun d'eux. Plus d'informations sur DI ici: angular.io/docs/ts/latest/guide/dependency-injection.html
Alexander Taylor
2

Vous devez ajouter un tableau de fournisseurs dans le décorateur @Component 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]
})
Shivang Gupta
la source
2

Dans mon cas, le passage de paramètres incorrects au constructeur génère cette erreur, l'idée de base à propos de cette erreur est que vous avez inconsciemment transmis des arguments incorrects à 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 cela en supprimant simplement cet argument.

Codiee
la source
2

Pour moi, j'ai eu cette erreur lorsque j'ai désactivé par erreur cette importation dans le fichier polyfills.ts, vous devez vous assurer qu'elle est importée pour éviter cette erreur.

/** 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';
Ahmed Elkoussy
la source
2

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

Dans AngularMaterial-2 DatePicker.

Donc, fondamentalement, j'ai oublié d'ajouter une @Injectableannotation.

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

@Injectable({
  providedIn: 'root'
})

L'erreur a disparu.

Muhammed Ozdogan
la source
Cela a fonctionné pour moi, mais je ne sais pas pourquoi. Le service et le composant qui le reçoit via DI doivent-ils être fournis dans: root pour que DI fonctionne?
Mike Furlender
2

Cette réponse peut être très utile pour ce problème. De plus, pour mon cas, exporter le service comme en defaultétait la cause.

FAUX:

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

CORRECT:

@Inject()
export class MobileService { ... }
otiai10
la source
2

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

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

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

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

sarora
la source
1

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

Pour les services mal orthographiés, j'ai pu déterminer quel service était le problème (j'en avais plusieurs 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 l'objet Object, object Object,? (ou quelque chose comme ça). Remarquez où le "?" est et c'est la position du service qui cause le problème.

homme male
la source
1

Bien que l' ordre des classes exportées à l'intérieur des barils ait été mentionné, le scénario suivant peut également produire le même effet.

Supposons que vous ayez des classes A, Bet Cexportées à partir du même fichier où cela Adépend Bet C:

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

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

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

Étant donné que les classes dépendantes (c'est-à-dire dans ce cas les classes Bet C) ne sont pas encore connues d'Angular, ( probablement au moment de l'exécution pendant le processus d'injection de dépendance d'Angular sur la classeA ), l'erreur est déclenchée.

Solution

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

c'est-à-dire que dans le cas ci-dessus, la classe Aest déclarée juste après la définition de ses dépendances:

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

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

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

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 MyEnumd'un enfant de MyComponentClass. Cela provoquait l' erreur Impossible de résoudre tous les paramètres .

En déplaçant MyEnumdans un dossier séparé 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 dépend de façon circulaire.

Menelaos Kotsollaris
la source
1

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 dans le fichier, vous pouvez obtenir cette erreur. Cela est dû au même problème «forwardRef» que d'autres ont mentionné. Pour le moment, VSCode n'est pas très utile pour vous montrer cette erreur et la compilation se compile avec succès.

L'exécution de la build avec --aotpeut masquer ce problème en raison de la façon dont le compilateur fonctionne (probablement lié au tremblement 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 sais pas 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.tsafin qu'il ne soit pas mélangé avec mes autres services.

Simon_Weaver
la source
1

Dans mon cas, c'était une référence circulaire. J'ai eu MyService appelant Myservice2 et MyService2 appelant MyService.

Pas bon :(

lucbonnin
la source
1

Dans mon cas, la raison était la suivante:

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

Par conséquent, lors de la tentative de création d'un objet A, le constructeur par défaut a échoué. Je n'ai aucune idée pourquoi ce n'était pas une erreur de compilation.

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

Vic Seedoubleyew
la source
1

Je t'ai eu!

Si aucune des réponses ci-dessus ne vous a aidé, vous importez peut-être un élément du même fichier où un composant injecte le service.

J'explique mieux:

Voici le fichier de service :

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

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

Voici le fichier composant :

@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 n'est pas à l'intérieur du même composant, mais juste à l'intérieur du même fichier. Déplacez le symbole (il peut s'agir d'une fonction, d'une constante, d'une classe, etc.) ailleurs et l'erreur disparaîtra

Cristian Traìna
la source
1

pour les versions angulaires 6 et plus récentes, essayez

@Injectable({
  providedIn: 'root'
})

.. juste au-dessus de votre classe de service sans autre ligne entre les deux

avantages

  • pas besoin d'ajouter le service à n'importe quel module (sera "auto-découvert")
  • le service sera un singleton (puisqu'il sera injecté dans root)

[ documents angulaires ]

lolcatzftw
la source