EXCEPCIÓN: no se pueden resolver todos los parámetros

431

He creado una aplicación básica en Angular 2, pero he encontrado un problema extraño en el que no puedo inyectar un servicio en uno de mis componentes. Sin embargo, se inyecta bien en cualquiera de los otros tres componentes que he creado.

Para empezar, este es el servicio:

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

}

Y el componente con el que se niega a trabajar:

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

}

El error que obtengo en la consola del navegador es este:

EXCEPCIÓN: No se pueden resolver todos los parámetros para HeaderComponent: (?).

Tengo el servicio en la función bootstrap, por lo que tiene un proveedor. Y parece que puedo inyectarlo en el constructor de cualquiera de mis otros componentes sin problema.

Keith Otto
fuente
14
Tal vez la importación? ¿Es '../'un index.ts(barril)? ¿Puedes intentar importarlo desde el archivo donde se declara directamente?
Günter Zöchbauer
¡Milagrosamente eso parece haberlo arreglado! Es extraño que no funcione usando el barril cuando los otros componentes con los que probé el servicio lo hicieron. Si desea publicar eso como respuesta en lugar de comentario, lo aceptaré.
Keith Otto
11
Generalmente una dependencia circular.
Gary
También tuve este problema con la dependencia circular. Vale la pena señalar que las versiones más nuevas del paquete web son mucho mejores para decirle esto
Enn
Parece dependencia circular, si usa angular> = 4 para que pueda deshacerse de intex.ts (barril) e importar todo lo que necesita directamente.
Rammgarot

Respuestas:

457

Importarlo desde el archivo donde se declara directamente en lugar del barril.

No sé qué causa exactamente el problema, pero lo vi mencionado varias veces (probablemente algún tipo de dependencia circular).

También debería ser reparable cambiando el orden de las exportaciones en el barril (no se conocen detalles, pero también se mencionó)

Günter Zöchbauer
fuente
16
esto es correcto si tiene, por ejemplo, un servicio inyectado en otro servicio que primero debe ser el primero en el barril.
Joao Garin
17
El equipo de Angular2 ya no recomienda barriles debido a muchos de estos problemas. Me alegra saber que podría ayudar :)
Günter Zöchbauer
13
No sabía que el equipo de Angular 2 no recomienda barriles. Si es así, deben tener en cuenta que en el glosario que analiza su beneficio. Y proyectos como angular2-webpack-starter no deberían usarlos.
Azul
3
Parece que esto se solucionó (no es un problema 2.0.2). Encuentro que los barriles siguen siendo útiles, especialmente cuando necesito importar varios modelos y servicios entre diferentes módulos. Esto import { cleanValues, getState, FirebaseService, NotificationService, ... } from '../../shared/services';fue un dolor cuando no funcionó (; NgModuleno es ayuda con los servicios de singleton ...
Sasxa
3
Argghh lo resolví cambiando el orden de las exportaciones en el archivo barril (index.ts) ... muchas gracias
Spock
331

Además de las respuestas anteriores dadas, parece que este error también se produce cuando a su servicio inyectable le falta el @Injectable()decorador real . Entonces, antes de depurar la cuestión de la dependencia cíclica y el orden de sus importaciones / exportaciones, haga una simple verificación si su servicio realmente se ha @Injectable()definido.

Esto se aplica a la última versión actual de Angular, Angular 2.1.0.

Abrí un problema sobre este asunto .

JP ten Berge
fuente
Sí, este error generalmente se debe a que olvidó agregar @Injectable y, por ejemplo, puede estar importando Routerdesde '@ angular / router' y sin ese inyectable, este error siempre ocurrirá (tan pronto como decida hacer una línea de uso de código que enrutador inyectado.
Eric Bishard
Impresionante respuesta, mi problema fue que agregué un método en mi servicio y no agregué un punto y coma después de la llave final. No tengo idea de por qué tiene que ser así, sin embargo, no es el caso en las clases de componentes ... ¡por ahora solo estoy contento de seguir adelante!
egimaben
Tenía un modelo simple que me dio este error. Usé el acceso directo donde creas tus propiedades en el constructor del modelo. Los tipos de las propiedades eran solo string e int. Entonces, de repente, este problema comenzó a ocurrir. Agregar @Injectable () solucionó el problema. Extraño porque ninguno de mis otros modelos tiene Injectable agregado. Tengo que agregar que actualicé bastantes bibliotecas antes de agregar este nuevo modelo. Posiblemente tuvo algo que ver con eso, pero ahora funciona. Gracias.
Moutono
@Moutono Correcto. Con un constructor vacío en su servicio, la inyección de dependencia no parece activarse y @injectable()no es necesaria. Lo cual es otra rareza en sí mismo. Sin embargo, aún así lo agregaría, simplemente para cuando alguna vez decidas inyectar algo.
JP ten Berge
Tenga en cuenta que si su servicio tiene una clase base que también necesita ser decorada con @Injectable ()
Sam Shiles
110

A partir de Angular, 2.2.3ahora hay una forwardRef()función de utilidad que le permite inyectar proveedores que aún no se han definido.

Por no definido, quiero decir que el mapa de inyección de dependencia no conoce el identificador. Esto es lo que sucede durante las dependencias circulares. Puede tener dependencias circulares en Angular que son muy difíciles de desenredar y ver.

export class HeaderComponent {
  mobileNav: boolean = false;

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

}

Agregar @Inject(forwardRef(() => MobileService))al parámetro del constructor en el código fuente de la pregunta original solucionará el problema.

Referencias

Angular 2 Manual: ForwardRef

Reenviar referencias en Angular 2

Reactgular
fuente
3
forwardRef()ya estaba allí en alfa ;-) Solo es necesario si el Mobileservicio se declara más abajo en el mismo archivo. Si las clases están en diferentes archivos, no hay necesidad de forwardRef()
hacerlo
44
Günter Zöchbauer, todavía estoy tratando de resolver el verdadero problema con mi código, pero mientras tanto forwardRef()ayudó a deshacerme del Can't resolve all parameters for ...mensaje. Al menos el componente funciona mientras busco una mejor solución al problema. (Y sí, la dependencia que falla se importa directamente de su archivo)
Nik
44
@ GünterZöchbauer He actualizado mi respuesta con referencias. No estoy tratando de quitarte tu respuesta, pero esto realmente resuelve el problema y la gente necesita saberlo. Si buscas en Google la pregunta, no hay resultados que digan usar forwardRef. Es muy dificil de encontrar. Ayer me llevó todo el día resolver este problema.
Reactgular
Extraño. Publiqué al menos una docena de respuestas que sugieren usarme a foreardRefmí mismo, pero ya no después de haber NgModulesido presentado. No estoy preocupado por perder repeticiones. Tengo curiosidad por saber por qué te encuentras con esto después de que esto ya no apareció desde hace unos meses. Tendré un vistazo más de cerca cuando vuelva a casa en unos días. Muchas gracias por los comentarios.
Günter Zöchbauer
2
Si alguien también se perdió con las importaciones: import {Component, Inject, ForwardRefFn, forwardRef} de '@ angular / core';
Natanael
69

INCORRECTO # 1: Olvidando al decorador:

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

INCORRECTO # 2: Omitiendo el símbolo "@":

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

INCORRECTO # 3: Omitiendo símbolos "()":

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

INCORRECTO # 4: "i" minúscula:

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

INCORRECTO # 5: Olvidó: importar {Inyectable} desde '@ angular / core';

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

CORRECTO:

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

Como ya se dijo, el problema es causado por el pedido de exportación dentro del barril que es causado por dependencias circulares.

Una explicación más detallada está aquí: https://stackoverflow.com/a/37907696/893630

Miguel
fuente
3
Ordenar no resolvió mi problema. No usar el barril lo hizo.
Michael Laffargue
21

También me encontré con esto al inyectar el servicio A en el servicio B y viceversa.

Creo que es bueno que esto falle rápidamente, ya que probablemente debería evitarse de todos modos . Si desea que sus servicios sean más modulares y reutilizables, es mejor evitar las referencias circulares tanto como sea posible. Esta publicación destaca las dificultades que la rodean.

Por lo tanto, tengo las siguientes recomendaciones:

  • Si cree que las clases interactúan con demasiada frecuencia (estoy hablando de la envidia de las características ), puede considerar fusionar los 2 servicios en 1 clase .
  • Si lo anterior no funciona para usted, considere usar un tercer servicio , (a EventService) que ambos servicios pueden inyectar para intercambiar mensajes.
Stephen Paul
fuente
1
Esto es definitivamente lo que me pasó, y este es el camino a seguir. Si sabe que tiene más de un servicio que requiere actualizaciones, use un EventService. Es más extensible ya que sin duda tendrá que aprovechar esos eventos a medida que extiende la aplicación basada en estos eventos.
themightybun
17

En beneficio de los buscadores; Tengo este error Era simplemente un símbolo @ perdido.

Es decir, esto produce el Can't resolve all parameters for MyHttpServiceerror.

Injectable()
export class MyHttpService{
}

Agregar el @símbolo que falta lo arregla.

@Injectable()
export class MyHttpService{
}
HockeyJ
fuente
2
En mi caso, agregué clases e interfaces adicionales entre @Injectable y la definición de clase de servicio, por lo que la clase de servicio ya no se marcó como inyectable.
Herc
Si olvida por completo el decorador @Injectable () en una clase de servicio que consume otros servicios inyectables, su servicio incorrectamente decorado también arrojará este error.
I. Buchan
10

En mi caso, necesitaba agregar import "core-js/es7/reflect";a mi aplicación para hacer el @Injectabletrabajo.

AJ Richardson
fuente
9

Otra posibilidad es no haber emitDecoratorMetadataestablecido en verdadero en tsconfig.json

{
  "compilerOptions": {

     ...

    "emitDecoratorMetadata": true,

     ...

    }

}
Stewart_R
fuente
8

Obtiene este error si tiene el servicio A que depende de una propiedad / método estático del servicio B y el servicio B en sí depende de la inyección de dependencia a través del servicio A. Por lo tanto, es una especie de dependencia circular, aunque no lo es, ya que la propiedad / método es estática. Probablemente un error que ocurre en combinación con AOT .

MK
fuente
También lo tuve cuando hay una dependencia en una función simplemente definida en el mismo archivo. Dividirlo en un archivo separado lo arregló.
Joe
1
Gracias a ti por mencionarlo. Me he encontrado en la situación exacta. No me di cuenta de que acceder a clases estáticas directamente puede tener algo que ver con el DI. Tenía este esquema: A -> By ambos usaban la misma clase estática. La solución con forwardRefayuda, pero voy a ver cómo esto podría desenredarse. Probablemente intentaré hacer un servicio real con esta clase estática (esto también conducirá a un mejor diseño).
Slava Fomin II
8

Además del @Injectable()decorador perdido

El @Injectable()decorador faltante en la clase abstracta produjo No se pueden resolver todos los parámetros para el servicio: (?) El decorador debe estar presente MyServicetanto como en la clase derivadaBaseService

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

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

En mi caso, sucedió porque no declaró el tipo para un parámetro constructor.

Tenía algo como esto:

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

y luego cambiarlo al código a continuación resolvió mi problema.

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

para mí fue solo falta de ()@Injectable. Proper is @Injectable ()

repo
fuente
O, en mi caso, eliminar accidentalmente el @
TDP
4

Eliminar parámetros del método constructor inyectable () lo resolvió para mi caso.

Matjaz Hirsman
fuente
Este fue exactamente mi problema también. ¡Vine a publicarlo pero descubrí que lo hiciste primero! +1
aesede
entonces, ¿cómo enviar los parámetros al servicio reutilizable?
3gwebtrain
2

Bueno, para mí el problema era aún más molesto, estaba usando un servicio dentro de un servicio y olvidé agregarlo como dependencia en el módulo de aplicación. Espero que esto ayude a alguien a ahorrar varias horas desglosando la aplicación solo para volver a compilarla

Ophir Stern
fuente
1
Solo me faltaba una @Injectanotación. Estaba pasando por alto exactamente lo que dice un poco el mensaje de error. Si no sospecha dependencias circulares, simplemente vaya a la clase mencionada en el error y mire todos los parámetros del constructor y cualquier miembro de la clase anotado @Injecty asegúrese de que está haciendo DI correctamente en todos ellos. Más sobre DI aquí: angular.io/docs/ts/latest/guide/dependency-injection.html
Alexander Taylor
2

Debe agregar la matriz de proveedores en el decorador @Component o en el módulo donde se declara su componente. Componente interno puede hacer lo siguiente:

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

En mi caso, pasar parámetros incorrectos al constructor genera este error, la idea básica sobre este error es que, sin saberlo, pasó algunos argumentos incorrectos a cualquier función.

export class ProductComponent {
    productList: Array<Product>;

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

Resolví esto simplemente eliminando ese argumento.

Codiee
fuente
2

Para mí, recibí este error cuando desactivé esta importación por error en el archivo polyfills.ts, debe asegurarse de que se importe para evitar ese error.

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

En mi caso, estaba intentando extender el método NativeDateAdapter" format(date: Date, displayFormat: Object)" para anular " ".

En AngularMaterial-2 DatePicker.

Así que básicamente olvidé agregar @Injectableanotaciones.

Después de agregar esto a mi clase "CustomDateAdapter":

@Injectable({
  providedIn: 'root'
})

El error se ha ido.

Muhammed Ozdogan
fuente
Esto funcionó para mí, pero no tengo idea de por qué. ¿Es necesario proporcionar tanto el servicio como el componente que lo recibe a través de DI In: root para que DI funcione?
Mike Furlender
2

Esta respuesta puede ser muy útil para este problema. Además, para mi caso, exportar el servicio como defaultfue la causa.

INCORRECTO:

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

CORRECTO:

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

Este puede ser un problema realmente difícil de depurar debido a la falta de comentarios en el error. Si le preocupa una dependencia cíclica real, esto es lo más importante que debe observar en el seguimiento de la pila a) el nombre del servicio b) el parámetro constructor en ese servicio que tiene un signo de interrogación, por ejemplo, si se ve así:

no se pueden resolver todos los parámetros para AuthService: ([objeto Objeto], [objeto Objeto], [objeto Objeto], [objeto Objeto],?)

entonces significa que el quinto parámetro es un servicio que también depende de AuthService. es decir, signo de interrogación, significa que no fue resuelto por DI.

A partir de ahí, solo necesita desacoplar los 2 servicios reestructurando el código.

sarora
fuente
1

He encontrado este error al escribir mal el nombre del servicio, es decir, constructor ( myService privado : MyService ).

Para los servicios mal escritos, pude determinar qué servicio era el problema (tenía varios listados en el constructor) inspeccionando la página en Chrome-> Console. Verá como parte del mensaje una lista de matriz de "parámetros" al mostrar el objeto Object, object Object,? (o algo así). Observe dónde está el "?" es y esa es la posición del servicio que está causando el problema.

Hombre masculino
fuente
1

Aunque puede haberse mencionado el pedido de clases exportadas desde barriles, el siguiente escenario también puede producir el mismo efecto.

Suponga que tiene clases A, By Cexportado desde dentro del mismo archivo en el que Adepende de By C:

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

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

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

Dado que las clases dependientes (es decir, en este caso, las clases By C) aún no son conocidas por Angular, ( probablemente en tiempo de ejecución durante el proceso de inyección de dependencia de Angular en la claseA ) se genera el error.

Solución

La solución es declarar y exportar las clases dependientes antes de la clase donde se realiza la DI.

es decir, en el caso anterior, la clase Ase declara justo después de definir sus dependencias:

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

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

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

En mi caso, estaba exportando una Clase y una Enum desde el mismo archivo de componente:

mComponent.component.ts:

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

Entonces, estaba tratando de usar MyEnumde un niño de MyComponentClass. Eso estaba causando el error No se puede resolver todos los parámetros .

Al moverme MyEnumen una carpeta separada de MyComponentClass, ¡eso resolvió mi problema!

Como mencionó Günter Zöchbauer, esto está sucediendo debido a que un servicio o componente depende circularmente.

Menelaos Kotsollaris
fuente
1

Si su servicio se define en el mismo archivo que un componente (que lo consume) y el servicio se define después del componente en el archivo, puede obtener este error. Esto se debe al mismo problema 'forwardRef' que otros han mencionado. En este momento, VSCode no es excelente para mostrarle este error y la compilación se compila correctamente.

Ejecutar la compilación con --aotpuede enmascarar este problema debido a la forma en que funciona el compilador (probablemente relacionado con la sacudida del árbol).

Solución: asegúrese de que el servicio esté definido en otro archivo o antes de la definición del componente. (No estoy seguro de si se puede utilizar forwardRef en este caso, pero parece torpe hacerlo).

Si tengo un servicio muy simple que está fuertemente vinculado a un componente (como un modelo de vista), por ejemplo. ImageCarouselComponent, Puedo nombrarlo ImageCarouselComponent.service.tspara que no se mezcle con mis otros servicios.

Simon_Weaver
fuente
1

En mi caso fue una referencia circular. Tenía MyService llamando a Myservice2 y MyService2 llamando a MyService.

No está bien :(

lucbonnin
fuente
1

En mi caso, la razón fue la siguiente:

  • mi servicio inyectable A extendió otra clase B
  • B tenía un constructor que requería un argumento
  • No había definido ningún constructor en A

Como consecuencia, al intentar crear un objeto A, el constructor predeterminado falló. No tengo idea de por qué esto no fue un error de compilación.

Lo solucioné simplemente agregando un constructor en A, que correctamente llamó al constructor de B.

Vic Seedoubleyew
fuente
1

Gotcha!

Si ninguna de las respuestas anteriores lo ayudó, tal vez esté importando algún elemento del mismo archivo donde un componente está inyectando el servicio.

Te explico mejor:

Este es el archivo de servicio :

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

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

Este es el archivo componente :

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

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

Por lo tanto, causa problemas incluso si el símbolo no está dentro del mismo componente, sino solo dentro del mismo archivo. Mueva el símbolo (puede ser una función, una constante, una clase, etc.) a otra parte y el error se desvanecerá.

Cristian Traìna
fuente
1

para angular 6 y versiones más nuevas, intente

@Injectable({
  providedIn: 'root'
})

.. justo encima de su clase de servicio sin otras líneas intermedias

ventajas

  • no es necesario agregar el servicio a ningún módulo (se "descubrirá automáticamente")
  • el servicio será un singleton (ya que se inyectará en la raíz)

[ documentos angulares ]

lolcatzftw
fuente