EXCEÇÃO: Não é possível resolver todos os parâmetros

431

Criei um aplicativo básico no Angular 2, mas encontrei um problema estranho no qual não posso injetar um serviço em um dos meus componentes. No entanto, ele injeta bem em qualquer um dos outros três componentes que criei.

Para iniciantes, este é o serviço:

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 o componente com o qual se recusa a trabalhar:

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

}

O erro que recebo no console do navegador é o seguinte:

EXCEÇÃO: Não é possível resolver todos os parâmetros para HeaderComponent: (?).

Eu tenho o serviço na função de inicialização, para que ele tenha um provedor. E eu pareço capaz de injetá-lo no construtor de qualquer um dos meus outros componentes sem problemas.

Keith Otto
fonte
14
Talvez a importação? É '../'um index.ts(barril)? Você pode tentar importá-lo do arquivo em que é declarado diretamente?
Günter Zöchbauer
Milagrosamente, isso parece ter consertado! Estranho que não funcionasse usando o barril quando os outros componentes com os quais testei o serviço funcionavam. Se você quiser postar isso como resposta, em vez de comentar, eu aceito.
Keith Otto
11
Geralmente uma dependência circular.
Gary
Eu tive esse problema com dependência circular também. Vale a pena notar que versões mais recentes do pacote de web são muito melhores em lhe dizendo isso
Enn
Parece dependência circular. Se você usar angular> = 4, poderá se livrar do intex.ts (barril) e importar tudo o que precisa diretamente.
precisa saber é o seguinte

Respostas:

457

Importe-o do arquivo em que é declarado diretamente em vez do barril.

Não sei o que exatamente causa o problema, mas o vi mencionado várias vezes (provavelmente algum tipo de dependência circular).

Também deve ser corrigível alterando a ordem das exportações no barril (não sabe detalhes, mas também foi mencionado)

Günter Zöchbauer
fonte
16
isso está correto se você tiver, por exemplo, um serviço injetado em outro serviço que primeiro precise ser o primeiro no barril.
João Garin
17
A equipe do Angular2 não recomenda mais barris por causa de muitos desses problemas. Fico feliz em ouvir que eu poderia ajudar :)
Günter Zöchbauer
13
Não sabia que a equipe do Angular 2 não recomenda barris. Nesse caso, eles devem observar isso no glossário que discute seus benefícios. E projetos como o angular2-webpack-starter não devem usá-los.
azul
3
Parece que isso foi corrigido (não é um problema 2.0.2). Acho que os barris ainda são úteis, principalmente quando preciso importar vários modelos e serviços entre diferentes módulos. Esta import { cleanValues, getState, FirebaseService, NotificationService, ... } from '../../shared/services';foi uma dor quando não funcionou (; NgModulehá ajuda com serviços únicos ...
Sasxa
3
Argghh Eu resolvi isso alterando a ordem das exportações no ficheiro barril (index.ts) .. muito obrigado
Spock
331

Além das respostas anteriores, parece que esse erro também é gerado quando o serviço injetável está faltando no @Injectable()decorador real . Portanto, antes de depurar o item de dependência cíclica e a ordem de suas importações / exportações, faça uma verificação simples se seu serviço realmente foi @Injectable()definido.

Isso se aplica ao Angular atual mais recente, o Angular 2.1.0.

Abri uma questão sobre esse assunto .

JP ten Berge
fonte
Sim, esse erro geralmente ocorre porque você esqueceu de adicionar @Injectable e, por exemplo, pode estar apenas importando o Router'@ angular / router' e sem esse injetável, esse erro sempre ocorrerá (assim que você decidir criar uma linha de código usar esse roteador injetado.
Eric Bishard 11/11
Resposta impressionante, meu problema foi que eu adicionei um método no meu serviço e não adicionei um ponto e vírgula após a chave final. Eu não tenho idéia do por que tem que ser assim, mas não é o caso nas classes de componentes ... por enquanto só fico feliz em seguir em frente!
egimaben 27/10
Eu tinha um modelo simples que me deu esse erro. Eu usei o atalho onde você cria suas propriedades no construtor do modelo. Os tipos das propriedades eram apenas string e int. De repente, esse problema começou a ocorrer. A adição de @Injectable () corrigiu o problema. Estranho, porque nenhum dos meus outros modelos adicionou o Injetável. Devo acrescentar que atualizei algumas bibliotecas antes de adicionar este novo modelo. Possivelmente tinha algo a ver com isso, mas trabalhando agora. Obrigado.
Moutono
@Moutono Correct. Com um construtor vazio em seu serviço, a injeção de dependência parece não ser acionada e @injectable()não é necessária. O que é outra singularidade em si. Por uma boa medida, ainda o adicionaria, simplesmente para quando você decidir injetar alguma coisa.
JP ten Berge
Tenha em mente que se o seu serviço tem uma classe base que também precisa ser decorado com @Injectable ()
Sam Shiles
110

A partir do Angular 2.2.3, agora existe uma forwardRef()função de utilitário que permite injetar provedores que ainda não foram definidos.

Por não definido, quero dizer que o mapa de injeção de dependência não conhece o identificador. É o que acontece durante dependências circulares. Você pode ter dependências circulares no Angular que são muito difíceis de desembaraçar e ver.

export class HeaderComponent {
  mobileNav: boolean = false;

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

}

A adição @Inject(forwardRef(() => MobileService))ao parâmetro do construtor no código-fonte da pergunta original corrigirá o problema.

Referências

Manual do Angular 2: ForwardRef

Encaminhar referências no Angular 2

Reactgular
fonte
3
forwardRef()já existia em alpha ;-) Só é necessário se o Mobileserviço for declarado mais abaixo no mesmo arquivo. Se as aulas estiverem em arquivos diferentes, não há necessidade deforwardRef()
Günter Zöchbauer 12/12/16
4
Günter Zöchbauer, ainda estou tentando descobrir o problema real do meu código, mas, enquanto isso forwardRef(), ajudou a me livrar da Can't resolve all parameters for ...mensagem. Pelo menos o componente está funcionando enquanto estou procurando uma solução melhor para o problema. (E sim, a dependência não é importado diretamente do seu arquivo)
Nik
4
@ GünterZöchbauer Atualizei minha resposta com referências. Não estou tentando tirar sua resposta, mas isso realmente resolve o problema e as pessoas precisam saber sobre ele. Se você pesquisar a pergunta no Google, não há resultados que digam usar forwardRef. É muito difícil de encontrar. Ontem me levou o dia inteiro para resolver esse problema.
Reactgular
Esquisito. Postei pelo menos uma dúzia de respostas que sugerem o uso de foreardRefmim mesmo, mas não mais depois de ter NgModulesido introduzida. Não estou preocupado em perder representantes. Só estou curioso por que você se deparou com isso depois que isso não apareceu mais desde alguns meses. Vou dar uma olhada mais de perto quando voltar para casa em alguns dias. Muito obrigado pelo feedback.
Günter Zöchbauer 12/12
2
Se alguém também se perdeu com as importações: import {Component, Inject, ForwardRefFn, forwardRef} de '@ angular / core';
Natanael
69

ERRO # 1: Esquecendo o Decorador:

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

ERRO # 2: Omitindo o símbolo "@":

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

ERRADO # 3: Omitindo símbolos "()":

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

ERRADO # 4: "i" minúsculo:

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

ERRO # 5: Você esqueceu: importar {Injetável} de '@ angular / core';

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

CORRIGIR:

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

Como já foi dito, o problema é causado pelo pedido de exportação dentro do barril, causado por dependências circulares.

Uma explicação mais detalhada está aqui: https://stackoverflow.com/a/37907696/893630

Michael
fonte
3
Encomendar não resolveu o meu problema. Não usando o cano fez.
Michael Laffargue
21

Eu também encontrei isso injetando o serviço A no serviço B e vice-versa.

Eu acho que é bom que isso falhe rápido, pois provavelmente deve ser evitado de qualquer maneira . Se você deseja que seus serviços sejam mais modulares e reutilizáveis, é melhor evitar referências circulares o máximo possível. Este post destaca as armadilhas que cercam isso.

Portanto, tenho as seguintes recomendações:

  • Se você sentir que as classes estão interagindo com muita frequência (estou falando de inveja de recursos ), convém mesclar os dois serviços em uma classe .
  • Se o exposto acima não funcionar, considere o uso de um terceiro serviço ( EventService), que ambos os serviços podem injetar para trocar mensagens.
Stephen Paul
fonte
1
Definitivamente, foi o que aconteceu comigo, e este é o caminho a percorrer. Se você sabe que possui mais de um serviço que exige atualizações, use um EventService. É mais extensível, pois você sem dúvida precisará acessar esses eventos à medida que estende o aplicativo com base nesses eventos.
precisa saber é o seguinte
17

Para o benefício dos pesquisadores; Eu recebi esse erro. Era simplesmente um símbolo @ ausente.

Ou seja, isso produz o Can't resolve all parameters for MyHttpServiceerro.

Injectable()
export class MyHttpService{
}

A adição do @símbolo ausente o corrige.

@Injectable()
export class MyHttpService{
}
HockeyJ
fonte
2
No meu caso, eu adicionei classes e interfaces extras entre @Injectable e a definição de classe de serviço, para que a classe de serviço não fosse mais marcada como injetável.
Herc
Se você esquecer completamente o decorador @Injectable () em uma classe de serviço que consome outros serviços injetáveis, seu serviço decorado incorretamente também gerará esse erro.
I. Buchan
10

No meu caso, eu precisava adicionar import "core-js/es7/reflect";ao meu aplicativo para fazer o @Injectabletrabalho.

AJ Richardson
fonte
9

Outra possibilidade é não ter emitDecoratorMetadatadefinido como true no tsconfig.json

{
  "compilerOptions": {

     ...

    "emitDecoratorMetadata": true,

     ...

    }

}
Stewart_R
fonte
8

Você recebe esse erro se tiver o serviço A que depende de uma propriedade estática / método de serviço B e o próprio serviço B depende do serviço A através da injeção de dependência. Portanto, é um tipo de dependência circular, embora não seja porque a propriedade / método é estático. Provavelmente um bug que ocorre em combinação com o AOT .

MK
fonte
Eu também tive isso quando há uma dependência de uma função simplesmente definida no mesmo arquivo. Dividindo-o em um arquivo separado, foi corrigido.
Joe
1
Obrigado por mencionar. Eu me encontrei na situação exata. Não percebi que o acesso direto a classes estáticas pode ter algo a ver com o DI. Eu tinha esse esquema: A -> Be os dois estavam usando a mesma classe estática. A solução forwardRefajuda, mas vou ver como isso pode ser resolvido. Provavelmente tentarei fazer um serviço real dessa classe estática (isso também levará a um design melhor).
Slava Fomin II
8

Além do @Injectable()decorador ausente

O @Injectable()decorador ausente na classe abstrata produziu o item Não é possível resolver todos os parâmetros de serviço: (?) O decorador precisa estar presente na MyServiceclasse derivada e na classe derivadaBaseService

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

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

No meu caso, aconteceu porque não declarei o tipo para um parâmetro do construtor.

Eu tinha algo parecido com isto:

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

e alterá-lo para o código abaixo resolveu meu problema.

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

para mim, foi apenas a falta do ()@Injectable. Adequado é @Injectable ()

repo
fonte
Ou, no meu caso, excluir acidentalmente o @
TDP
4

A remoção de parâmetros do método injetável constructor () resolveu o problema para o meu caso.

Matjaz Hirsman
fonte
Este foi exatamente o meu problema também. Eu vim para publicá-lo, mas descobri que você primeiro! +1
aesede
então como enviar os parâmetros para o serviço reutilizável?
3gwebtrain
2

Bem, para mim, o problema era ainda mais irritante, eu estava usando um serviço dentro de um serviço e esqueci de adicioná-lo como dependência no appModule! Espero que isso ajude alguém a economizar várias horas quebrando o aplicativo apenas para construí-lo novamente

Ophir Stern
fonte
1
Só faltava uma @Injectanotação. Eu estava ignorando exatamente o que a mensagem de erro diz um pouco. Se você não suspeitar de dependências circulares, vá para a classe mencionada no erro e veja todos os parâmetros do construtor e todos os membros da classe anotados @Injecte verifique se você está executando o DI corretamente em todos eles. Mais sobre o DI aqui: angular.io/docs/ts/latest/guide/dependency-injection.html
Alexander Taylor
2

Você precisa adicionar uma matriz de provedores no decorador @Component ou no módulo em que seu componente é declarado. Componente interno, você pode fazer o seguinte:

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

No meu caso, passar parâmetros errados para o construtor gera esse erro, a idéia básica sobre esse erro é que você passou inadvertidamente alguns argumentos errados para qualquer função.

export class ProductComponent {
    productList: Array<Product>;

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

Resolvi isso apenas removendo esse argumento.

Codiee
fonte
2

Para mim, recebi esse erro quando desabilitei esta importação por engano no arquivo polyfills.ts, é necessário garantir que ela seja importada para evitar esse erro.

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

No meu caso, eu estava tentando estender " NativeDateAdapter" para substituir "format(date: Date, displayFormat: Object) " o método.

Em AngularMaterial-2 DatePicker.

Então, basicamente, eu esqueci de adicionar @Injectable anotação.

Depois de adicionar isso à minha classe "CustomDateAdapter":

@Injectable({
  providedIn: 'root'
})

Ocorreu um erro.

Muhammed Ozdogan
fonte
Isso funcionou para mim, mas não tenho idéia do porquê. O serviço e o componente que o recebe através do DI precisam ser fornecidos em: root para que o DI funcione?
25719 Mike Furlender
2

Esta resposta pode ser muito útil para esse problema. Além disso, no meu caso, exportar o serviço como defaultfoi a causa.

ERRADO:

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

CORRIGIR:

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

Esse pode ser um problema realmente difícil de depurar devido à falta de feedback no erro. Se você está preocupado com uma dependência cíclica real, aqui está a coisa mais importante a ser observada no rastreamento da pilha: a) o nome do serviço b) o parâmetro construtor nesse serviço que possui um ponto de interrogação, por exemplo, se estiver assim:

não é possível resolver todos os parâmetros para AuthService: ([objeto Objeto], [objeto Objeto], [objeto Objeto], [objeto Objeto],?)

significa que o quinto parâmetro é um serviço que também depende do AuthService. ou seja, ponto de interrogação, significa que não foi resolvido pelo DI.

A partir daí, você só precisa dissociar os 2 serviços reestruturando o código.

sarora
fonte
1

Eu encontrei esse erro digitando incorretamente o nome do serviço, ou seja, construtor (private myService: MyService ).

Para serviços com erros de ortografia, consegui determinar qual serviço era o problema (eu tinha vários listados no construtor) inspecionando a página no Chrome-> Console. Você verá como parte da mensagem uma lista de array de "parâmetros" exibindo o objeto Object, objeto Object,? (ou algo assim). Observe onde o "?" é e essa é a posição do serviço que está causando o problema.

homem
fonte
1

Embora a encomenda das classes exportadas de dentro de barris possa ter sido mencionada, o cenário a seguir também pode produzir o mesmo efeito.

Suponha que você tenha classes A, Be Cexportadas de dentro do mesmo arquivo em que Adepende Be C:

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

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

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

Como as classes dependentes (ou seja, neste caso, classes Be C) ainda não são conhecidas pelo Angular, ( provavelmente em tempo de execução durante o processo de injeção de dependência do Angular na classeA ), o erro é gerado.

Solução

A solução é declarar e exportar as classes dependentes antes da classe em que o DI é feito.

ou seja, no caso acima, a classe Aé declarada logo após a definição de suas dependências:

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

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

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

No meu caso, eu estava exportando uma classe e um enum do mesmo arquivo de componente:

mComponent.component.ts:

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

Então, eu estava tentando usar MyEnumde um filho de MyComponentClass. Isso estava causando o erro Não é possível resolver todos os parâmetros .

Ao mover MyEnumuma pasta separada de MyComponentClass, isso resolveu meu problema!

Como Günter Zöchbauer mencionou, isso está acontecendo devido a um serviço ou componente ser circularmente dependente.

Menelaos Kotsollaris
fonte
1

Se o seu serviço estiver definido no mesmo arquivo que um componente (que o consome) e o serviço for definido após o componente no arquivo, você poderá receber este erro. Isso ocorre devido ao mesmo problema 'forwardRef' mencionado por outros. No momento, o VSCode não é bom em mostrar esse erro e a compilação é compilada com êxito.

A execução da compilação --aotpode mascarar esse problema devido à maneira como o compilador funciona (provavelmente relacionado ao tremor da árvore).

Solução: verifique se o serviço está definido em outro arquivo ou antes da definição do componente. (Não tenho certeza se o forwardRef pode ser usado nesse caso, mas parece desajeitado fazê-lo).

Se eu tiver um serviço muito simples que esteja fortemente vinculado a um componente (como um modelo de exibição) - por exemplo. ImageCarouselComponent, Posso citar o nome ImageCarouselComponent.service.tspara que não se confunda com meus outros serviços.

Simon_Weaver
fonte
1

No meu caso, era uma referência circular. Eu tinha o MyService chamando Myservice2 e o MyService2 chamando MyService.

Não é bom :(

lucbonnina
fonte
1

No meu caso, o motivo foi o seguinte:

  • meu serviço injetável A estendeu outra classe B
  • B tinha um construtor que exigia um argumento
  • Eu não havia definido nenhum construtor em A

Como conseqüência, ao tentar criar um objeto A, o construtor padrão falhou. Não faço ideia por que isso não foi um erro de compilação.

Para consertá-lo, basta adicionar um construtor em A, que corretamente chamou o construtor de B.

Vic Seedoubleyew
fonte
1

Peguei vocês!

Se nenhuma das respostas acima o ajudou, talvez você esteja importando algum elemento do mesmo arquivo em que um componente está injetando o serviço.

Eu explico melhor:

Este é o arquivo de serviço :

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

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

Este é o arquivo de componente :

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

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

Isso causa problemas, mesmo que o símbolo não esteja dentro do mesmo componente, mas apenas dentro do mesmo arquivo. Mova o símbolo (pode ser uma função, uma constante, uma classe e assim por diante ...) em outro lugar e o erro desaparecerá

Cristian Traìna
fonte
1

para angular 6 e versões mais recentes, tente

@Injectable({
  providedIn: 'root'
})

.. logo acima da sua classe de serviço, sem outras linhas no meio

vantagens

  • não é necessário adicionar o serviço a nenhum módulo (será "descoberto automaticamente")
  • serviço será um singleton (já que será injetado na raiz)

[ documentos angulares ]

lolcatzftw
fonte