ECCEZIONE: impossibile risolvere tutti i parametri


431

Ho creato un'app di base in Angular 2, ma ho riscontrato uno strano problema in cui non riesco a iniettare un servizio in uno dei miei componenti. Inietta bene in uno qualsiasi degli altri tre componenti che ho creato, tuttavia.

Per cominciare, questo è il servizio:

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;
  }

}

E il componente con cui si rifiuta di lavorare:

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'errore che ottengo nella console del browser è questo:

ECCEZIONE: impossibile risolvere tutti i parametri per HeaderComponent: (?).

Ho il servizio nella funzione bootstrap quindi ha un provider. E sembra che sia in grado di iniettarlo senza problemi nel costruttore di uno qualsiasi dei miei altri componenti.


14
Forse l'importazione? È '../'un index.ts(barile)? Puoi provare a importarlo dal file in cui è invece dichiarato direttamente?
Günter Zöchbauer,

Miracolosamente sembra averlo risolto! Strano che non funzionasse con la canna quando lo facevano gli altri componenti con cui ho provato il servizio. Se vuoi pubblicarlo come risposta anziché come commento, lo accetterò.
Keith Otto,

11
Generalmente una dipendenza circolare.
Gary,

Ho avuto questo problema anche con la dipendenza circolare. Vale la pena notare che le nuove versioni del web pack sono molto meglio nel dirti questo
Enn

Sembra una dipendenza circolare, se usi angolare> = 4 in modo da poter eliminare intex.ts (barile) e importare direttamente tutto ciò di cui hai bisogno.
Rammgarot,

Risposte:


457

Importalo dal file dove viene dichiarato direttamente anziché dalla canna.

Non so che cosa causi esattamente il problema, ma l'ho visto menzionato più volte (probabilmente una sorta di dipendenza circolare).

Dovrebbe anche essere riparabile modificando l'ordine delle esportazioni nel barile (non conosco i dettagli, ma è stato menzionato anche)


16
questo è corretto se ad esempio un servizio è stato iniettato in un altro servizio che per primo deve venire per primo nella canna.
Joao Garin,

17
Il team di Angular2 non raccomanda più i barili a causa di molti di questi problemi. Sono contento di sapere che potrei aiutare :)
Günter Zöchbauer,

13
Non sapevo che il team di Angular 2 non raccomandasse i barili. Se è così, dovrebbero notare che nel glossario che discute i loro benefici. E progetti come angular2-webpack-starter non dovrebbero usarli.
Blu,

3
Sembra che sia stato risolto (non un problema 2.0.2). Trovo che i barili siano ancora utili, specialmente quando devo importare diversi modelli e servizi tra moduli diversi. Questo è import { cleanValues, getState, FirebaseService, NotificationService, ... } from '../../shared/services';stato un dolore quando non ha funzionato (; NgModulenon è di aiuto con i servizi singleton ...
Sasxa,

3
Argghh l'ho risolto cambiando l'ordine delle esportazioni nel file barile (index.ts) .. grazie mille
Spock

331

Oltre alle precedenti risposte fornite, sembra che questo errore venga generato anche quando nel tuo servizio iniettabile manca l'effettivo @Injectable()decoratore. Quindi, prima di eseguire il debug della cosa di dipendenza ciclica e l'ordine delle tue importazioni / esportazioni, fai un semplice controllo se il tuo servizio è stato effettivamente @Injectable()definito.

Questo vale per l'attuale Angular più recente, Angular 2.1.0.

Ho aperto un problema su questo argomento .


Sì, questo errore è in genere dovuto al fatto che hai dimenticato di aggiungere @Injectable e, ad esempio, potresti semplicemente importare Routerda "@ angular / router" e senza tale iniettabile, questo errore si verificherà sempre (non appena decidi di fare una riga di utilizzare il codice che iniettato router.
Eric Bishard

Risposta fantastica, il mio problema era che ho aggiunto un metodo al mio servizio e non ho aggiunto un punto e virgola dopo il controvento finale. Non ho idea del perché debba essere così, ma non è così nelle classi di componenti ... per ora sono solo felice di andare avanti!
egimaben,

Avevo un modello semplice che mi ha dato questo errore. Ho usato il collegamento in cui si creano le proprietà nel costruttore del modello. I tipi di proprietà erano solo stringa e int. Quindi improvvisamente questo problema ha iniziato a verificarsi. L'aggiunta di @Injectable () ha risolto il problema. Strano perché nessuno dei miei altri modelli ha aggiunto iniettabili. Devo aggiungere che ho aggiornato alcune librerie prima di aggiungere questo nuovo modello. Forse aveva qualcosa a che fare con esso, ma ora funziona. Grazie.
Moutono,

@Moutono Correct. Con un costruttore vuoto al tuo servizio, l'iniezione di dipendenza non sembra essere innescata e @injectable()non è necessaria. Qual è un'altra stranezza su se stesso. Per buona parte, lo aggiungerei comunque, semplicemente per quando dovresti mai decidere di iniettare qualcosa.
JP dieci Berge,

Ricorda che se il tuo servizio ha una classe base che deve essere decorata anche con @Injectable ()
Sam Shiles

110

A partire da Angular 2.2.3ora esiste una forwardRef()funzione di utilità che consente di iniettare provider non ancora definiti.

Per non definito, intendo che la mappa di iniezione delle dipendenze non conosce l'identificatore. Questo è ciò che accade durante le dipendenze circolari. Puoi avere dipendenze circolari in Angolare che sono molto difficili da districare e vedere.

export class HeaderComponent {
  mobileNav: boolean = false;

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

}

L'aggiunta @Inject(forwardRef(() => MobileService))al parametro del costruttore nel codice sorgente della domanda originale risolverà il problema.

Riferimenti

Manuale angolare 2: ForwardRef

Riferimenti in avanti in Angolare 2


3
forwardRef()era già presente in alpha ;-) È necessario solo se il Mobileservizio è dichiarato più in basso nello stesso file. Se le classi si trovano in file diversi, non è necessarioforwardRef()
Günter Zöchbauer

4
Günter Zöchbauer, sto ancora cercando di capire il vero problema con il mio codice, ma nel frattempo mi forwardRef()ha aiutato a sbarazzarmi del Can't resolve all parameters for ...messaggio. Almeno il componente funziona mentre sto cercando una soluzione migliore al problema. (E sì, la dipendenza fallita viene importata direttamente dal suo file)
Nik

4
@ GünterZöchbauer Ho aggiornato la mia risposta con riferimenti. Non sto cercando di togliere la tua risposta, ma questo in realtà risolve il problema e le persone devono saperlo. Se vai su Google la domanda non ci sono risultati che dicono di usare forwardRef. È molto difficile da trovare. Mi ha preso tutto il giorno ieri per risolvere questo problema.
Reactgular,

Strano. Ho pubblicato almeno una dozzina di risposte che suggeriscono di usare foreardRefme stesso ma non più dopo che è NgModulestato introdotto. Non sono preoccupato di perdere ripetizioni. Sono solo curioso di sapere perché ti sei imbattuto in questo dopo che questo non è più apparso da alcuni mesi. Darò un'occhiata più da vicino quando torno a casa tra qualche giorno. Grazie tante per il feedback.
Günter Zöchbauer,

2
Se qualcuno si fosse perso anche delle importazioni: import {Component, Inject, ForwardRefFn, forwardRef} da '@ angular / core';
Natanael,

69

SBAGLIATO # 1: dimenticare il decoratore:

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

SBAGLIATO # 2: omettere il simbolo "@":

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

SBAGLIATO # 3: omettere i simboli "()":

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

SBAGLIATO # 4: "i" minuscola:

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

SBAGLIATO # 5: hai dimenticato: importare {Injectable} da '@ angular / core';

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

CORRETTA:

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


21

Ho anche riscontrato questo iniettando il servizio A nel servizio B e viceversa.

Penso che sia una buona cosa che questo fallisca rapidamente, poiché probabilmente dovrebbe essere evitato comunque . Se vuoi che i tuoi servizi siano più modulari e riutilizzabili, è meglio evitare riferimenti circolari il più possibile. Questo post evidenzia le insidie ​​che lo circondano.

Pertanto, ho i seguenti consigli:

  • Se ritieni che le classi interagiscano troppo spesso (sto parlando di invidia delle funzionalità ), potresti prendere in considerazione l' idea di unire i 2 servizi in 1 classe .
  • Se quanto sopra non funziona per te, considera l'utilizzo di un terzo servizio , (a EventService) che entrambi i servizi possono iniettare per scambiare messaggi.

1
Questo è sicuramente quello che mi è successo e questa è la strada da percorrere. Se sai di avere più di un servizio che richiede aggiornamenti, usa un EventService. È più estensibile poiché senza dubbio dovrai attingere a quegli eventi man mano che estendi l'applicazione in base a questi eventi.
themightybun

17

A beneficio dei ricercatori; Ho ricevuto questo errore. Era semplicemente un simbolo @ mancante.

Cioè Questo produce l' Can't resolve all parameters for MyHttpServiceerrore.

Injectable()
export class MyHttpService{
}

L'aggiunta del @simbolo mancante lo risolve.

@Injectable()
export class MyHttpService{
}

2
Nel mio caso, avevo aggiunto ulteriori classi e interfacce tra @Injectable e la definizione della classe di servizio, quindi la classe di servizio non era più contrassegnata come iniettabile.
Herc,

Se dimentichi completamente il decoratore @Injectable () in una classe di servizio che consuma altri servizi iniettabili, anche il tuo servizio decorato in modo errato genererà questo errore.
I. Buchan,

10

Nel mio caso, ho dovuto aggiungere import "core-js/es7/reflect";alla mia applicazione per @Injectablefunzionare.


9

Un'altra possibilità non è stata emitDecoratorMetadataimpostata su true in tsconfig.json

{
  "compilerOptions": {

     ...

    "emitDecoratorMetadata": true,

     ...

    }

}

8

Questo errore viene visualizzato se si dispone del servizio A che dipende da una proprietà / metodo statico del servizio B e il servizio B stesso dipende dal servizio A tramite l'iniezione di dipendenza. Quindi è una specie di dipendenza circolare, anche se non lo è poiché la proprietà / metodo è statico. Probabilmente un bug che si verifica in combinazione con AOT .


L'ho avuto anche quando c'è una dipendenza da una funzione semplicemente definita nello stesso file. Dividendolo in un file separato, è stato risolto.
Joe,

1
Grazie per averlo menzionato. Mi sono trovato nella situazione esatta. Non mi ero reso conto che l'accesso diretto alle classi statiche potesse avere qualcosa a che fare con il DI. Avevo questo schema: A -> Bed entrambi stavano usando la stessa classe statica. La soluzione con forwardRefaiuta, ma vado a vedere come questo potrebbe essere districato. Probabilmente proverò a realizzare un vero servizio da questa classe statica (questo porterà anche a un design migliore).
Slava Fomin II,

8

Oltre al @Injectable()decoratore mancante

Il @Injectable()decoratore mancante nella classe astratta ha prodotto Impossibile risolvere tutti i parametri per il servizio: (?) Il decoratore deve essere presente MyServicesia nella classe derivataBaseService

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

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

7

Nel mio caso, è successo perché non ho dichiarato il tipo per un parametro del costruttore.

Ho avuto qualcosa del genere:

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

e poi cambiarlo nel codice qui sotto risolto il mio problema.

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


4

La rimozione dei parametri dal metodo del costruttore iniettabile () ha risolto il problema nel mio caso.


Anche questo era esattamente il mio problema. Sono venuto per pubblicarlo, ma ho scoperto che l'hai fatto prima! +1
aesede

quindi come inviare i parametri al servizio riutilizzabile?
3gwebtrain,


2

Bene, per me il problema era ancora più fastidioso, stavo usando un servizio all'interno di un servizio e ho dimenticato di aggiungerlo come dipendenza nell'appModule! Spero che questo aiuti qualcuno a risparmiare diverse ore rompendo l'app solo per ricostruirla di nuovo


1
Mi mancava solo @Injectun'annotazione. Stavo trascurando esattamente cosa dice un po 'il messaggio di errore. Se non sospetti dipendenze circolari, vai semplicemente alla classe menzionata nell'errore e guarda tutti i parametri del costruttore e tutti i membri della classe annotati @Injecte assicurati di fare DI proprio su tutti. Maggiori informazioni su DI qui: angular.io/docs/ts/latest/guide/dependency-injection.html
Alexander Taylor

2

Devi aggiungere un array di provider in @Component decorator o nel modulo in cui è dichiarato il tuo componente. All'interno del componente puoi fare come di seguito:

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

2

Nel mio caso il passaggio di parametri errati al costruttore genera questo errore, l'idea di base di questo errore è che inconsapevolmente hai passato alcuni argomenti sbagliati a qualsiasi funzione.

export class ProductComponent {
    productList: Array<Product>;

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

Ho risolto questo semplicemente rimuovendo tale argomento.


2

Per me, ho ricevuto questo errore quando ho disabilitato erroneamente questa importazione nel file polyfills.ts, è necessario assicurarsi che sia importato per evitare tale errore.

/** 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

Nel mio caso stavo cercando di estendere il metodo NativeDateAdapter" format(date: Date, displayFormat: Object)" per sovrascrivere " ".

In AngularMaterial-2 DatePicker.

Quindi sostanzialmente ho dimenticato di aggiungere l' @Injectableanotazione.

Dopo averlo aggiunto alla mia classe "CustomDateAdapter":

@Injectable({
  providedIn: 'root'
})

L'errore è andato.


Questo ha funzionato per me, ma non ho idea del perché. È necessario fornire sia il servizio che il componente che lo riceve tramite DIInIn: root affinché DI funzioni?
Mike Furlender,

2

Questa risposta potrebbe essere molto utile per questo problema. Inoltre, nel mio caso, l'esportazione del servizio è defaultstata la causa.

SBAGLIATO:

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

CORRETTA:

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

2

Questo può essere un problema davvero difficile da debug a causa della mancanza di feedback nell'errore. Se sei preoccupato per un'effettiva dipendenza ciclica, ecco la cosa più importante da guardare nella traccia dello stack a) il nome del servizio b) il parametro del costruttore in quel servizio che ha un punto interrogativo, ad esempio se assomiglia a questo:

impossibile risolvere tutti i parametri per AuthService: ([oggetto oggetto], [oggetto oggetto], [oggetto oggetto], [oggetto oggetto],?)

quindi significa che il 5o parametro è un servizio che dipende anche da AuthService. cioè punto interrogativo, significa che non è stato risolto da DI.

Da lì, devi solo disaccoppiare i 2 servizi ristrutturando il codice.


1

Ho riscontrato questo errore digitando erroneamente il nome del servizio, ovvero costruttore ( myService privato : MyService ).

Per i servizi con errori di ortografia, sono stato in grado di determinare quale servizio era il problema (ne avevo elencati diversi nel costruttore) controllando la pagina in Chrome-> Console. Vedrai come parte del messaggio un elenco di parametri "parametri" visualizzando oggetto Oggetto, oggetto Oggetto,? (o qualcosa di simile). Notare dove il "?" è e quella è la posizione del servizio che sta causando il problema.


1

Sebbene l' ordinamento delle classi esportate all'interno dei barili possa essere stato menzionato, anche il seguente scenario può produrre lo stesso effetto.

Supponiamo di avere classi A, Be Cesportato dal all'interno dello stesso file in cui Adipende Be C:

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

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

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

Poiché le classi dipendenti (ovvero in questo caso classi Be C) non sono ancora note ad Angular, ( probabilmente in fase di esecuzione durante il processo di iniezione di dipendenza Angular sulla classeA ), viene generato l'errore.

Soluzione

La soluzione è dichiarare ed esportare le classi dipendenti prima della classe in cui viene eseguita la DI.

cioè nel caso sopra riportato la classe Aviene dichiarata subito dopo aver definito le sue dipendenze:

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

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

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

1

Nel mio caso, stavo esportando una classe e un'enum dallo stesso file componente:

mComponent.component.ts:

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

Quindi, stavo cercando di usare MyEnumda un bambino di MyComponentClass. Ciò stava causando l' errore Impossibile risolvere tutti i parametri .

Spostandomi MyEnumin una cartella separata da MyComponentClass, ciò ha risolto il mio problema!

Come menzionato da Günter Zöchbauer, ciò sta accadendo perché un servizio o un componente è circolarmente dipendente.


1

Se il servizio è definito nello stesso file di un componente (che lo consuma) e il servizio è definito dopo il componente nel file, è possibile che venga visualizzato questo errore. Ciò è dovuto allo stesso problema 'forwardRef' che altri hanno menzionato. Al momento VSCode non è eccezionale nel mostrarti questo errore e la compilazione si compila con successo.

L'esecuzione della build con --aotpuò mascherare questo problema a causa del modo in cui funziona il compilatore (probabilmente correlato al tremolio dell'albero).

Soluzione: assicurarsi che il servizio sia definito in un altro file o prima della definizione del componente. (Non sono sicuro che forwardRef possa essere usato in questo caso, ma sembra goffo farlo).

Se ho un servizio molto semplice che è fortemente legato a un componente (un po 'come un modello di vista) - ad es. ImageCarouselComponent, Potrei nominarloImageCarouselComponent.service.ts modo che non si confonda con gli altri miei servizi.


1

Nel mio caso era un riferimento circolare. Ho avuto MyService che chiamava Myservice2 e MyService2 che chiamava MyService.

Non bene :(


1

Nel mio caso, il motivo era il seguente:

  • il mio servizio iniettabile A ha esteso un'altra classe B
  • B aveva un costruttore che richiedeva una discussione
  • Non avevo definito alcun costruttore in A

Di conseguenza, quando si tenta di creare un oggetto A, il costruttore predefinito non è riuscito. Non ho idea del perché questo non sia stato un errore di compilazione.

Ho risolto semplicemente aggiungendo un costruttore in A, che correttamente chiamato costruttore di B.


1

Gotcha!

Se nessuna delle risposte precedenti ti ha aiutato, forse stai importando qualche elemento dallo stesso file cui un componente sta iniettando il servizio.

Spiego meglio:

Questo è il file di servizio :

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

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

Questo è il file componente :

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

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

Quindi causa problemi anche se il simbolo non è all'interno dello stesso componente, ma solo all'interno dello stesso file. Sposta il simbolo (può essere una funzione, una costante, una classe e così via ...) altrove e l'errore svanirà


1

per angolare 6 e versioni più recenti, provare

@Injectable({
  providedIn: 'root'
})

.. proprio sopra la tua classe di servizio senza altre linee in mezzo

vantaggi

  • non è necessario aggiungere il servizio a nessun modulo (verrà "scoperto automaticamente")
  • il servizio sarà un singleton (poiché verrà iniettato nella radice)

[ documenti angolari ]

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.