角度DI错误 - 例外:无法解析所有参数

时间:2016-06-23 17:07:45

标签: angular angular2-di

我已经在Angular中构建了一个基本的应用程序,但是我遇到了一个奇怪的问题,我无法将服务注入到我的一个组件中。它注入了我创建的其他三个组件中的任何一个。

首先,这是服务:

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

}

它拒绝使用的组件:

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

}

我在浏览器控制台中遇到的错误是:

  

例外:无法解析HeaderComponent的所有参数:(?)。

我在bootstrap函数中有服务,所以它有一个提供者。我似乎能够毫无问题地将它注入我的任何其他组件的构造函数中。

47 个答案:

答案 0 :(得分:398)

从直接声明它的文件中导入它而不是桶。

我不知道究竟是什么导致了这个问题,但我看到它多次提到(可能是某种循环依赖)。

也可以通过改变桶中出口的顺序来解决(不知道细节,但也提到了)

答案 1 :(得分:286)

除了之前给出的答案之外,当您的注射服务缺少实际的@Injectable()装饰器时,似乎也会抛出此错误。因此,在调试循环依赖项事项和导入/导出的顺序之前,请检查您的服务是否实际定义了@Injectable()

这适用于当前的Angular最新版Angular 2.1.0。

I opened an issue on this matter

答案 2 :(得分:95)

从Angular 2.2.3开始,现在有一个forwardRef()实用程序函数,允许您注入尚未定义的提供程序。

未定义,我的意思是依赖注入映射不知道标识符。这是循环依赖期间发生的情况。你可以在Angular中使用非常难以解开的循环依赖关系。

export class HeaderComponent {
  mobileNav: boolean = false;

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

}

在原始问题的源代码中将@Inject(forwardRef(() => MobileService))添加到构造函数的参数中将解决问题。

参考

Angular 2 Manual: ForwardRef

Forward references in Angular 2

答案 3 :(得分:53)

错误#1:忘记装饰者:

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

错误#2:省略" @"符号:

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

错误#3:省略"()"符号:

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

错误#4:小写"我":

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

错误#5:你忘记了: 来自' @ angular / core'

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

<强>正确:

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

答案 4 :(得分:24)

如前所述,问题是由于循环依赖导致的桶内导出排序造成的。

更详细的解释如下:https://stackoverflow.com/a/37907696/893630

答案 5 :(得分:20)

我也通过将服务A注入服务B来遇到这种情况,反之亦然。

我觉得这很快就会失败,因为它应该可以避免。如果您希望您的服务更加模块化/可重复使用,最好尽可能避免循环引用。这个post凸显了周围的陷阱。

因此,我有以下建议:

  • 如果你觉得这些课程经常互动(我在谈论feature envy),你可能想要考虑将2个服务合并为1个课程
  • 如果以上内容对你不起作用,请考虑使用第三项服务,(EventService)两种服务都可以注入以便交换消息。

答案 6 :(得分:17)

为了搜索者的利益;我收到了这个错误。它只是一个缺失的@符号。

即。这会产生Can't resolve all parameters for MyHttpService错误。

Injectable()
export class MyHttpService{
}

添加缺少的@符号可以修复它。

@Injectable()
export class MyHttpService{
}

答案 7 :(得分:8)

就我而言,我需要将import "core-js/es7/reflect";添加到我的应用程序中以使@Injectable正常工作。

答案 8 :(得分:8)

如果您的服务 A 取决于静态属性/方法服务 B 且服务,则会出现此错误B 本身取决于服务 A 槽依赖注入。所以它是一种循环依赖,虽然它不是属性/方法是静态的。可能是与 AOT 结合使用的错误。

答案 9 :(得分:7)

除了缺少的@Injectable()装饰者

抽象类中缺少@Injectable()装饰器生成了无法解析服务的所有参数:(?) 装饰器需要存在于MyService以及派生类BaseService

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

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

答案 10 :(得分:6)

在我的情况下,它发生了,因为我没有声明构造函数参数的类型。

我有这样的事情:

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

然后将其更改为下面的代码解决了我的问题。

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

答案 11 :(得分:5)

从injectable constructor()方法中删除参数解决了我的问题。

答案 12 :(得分:5)

对我来说,@ Injectable中缺少()。适当的是@Injectable()

答案 13 :(得分:4)

在我的情况下,由于插件Augury,禁用它将工作正常。替代选项是aot,也有效。

@ Boboss74的所有学分,他在这里发布了答案:https://github.com/angular/angular/issues/23958

答案 14 :(得分:4)

另一种可能性是在tsconfig.json

中将emitDecoratorMetadata设置为true
{
  "compilerOptions": {

     ...

    "emitDecoratorMetadata": true,

     ...

    }

}

答案 15 :(得分:2)

您必须在@Component装饰器或声明组件的模块中添加providers数组。在内部组件中,您可以执行以下操作:

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

答案 16 :(得分:2)

在我的情况下,将错误的参数传递给构造函数会生成此错误,关于此错误的基本想法是您在不知不觉中将一些错误的args传递给任何函数。

export class ProductComponent {
    productList: Array<Product>;

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

我通过删除该参数解决了这个问题。

答案 17 :(得分:2)

对我来说,当我在polyfills.ts文件中 错误地禁用 这个导入时出现此错误,您需要确保导入它以避免该错误。< / p>

curl -X POST \
  http://localhost:8000/sendData/ \
  -H 'authorization: Token b67d31c42d98b3c97b28c737629dca63ef5043fc' \
  -H 'cache-control: no-cache' \
  -H 'client_cdata: virat' \
  -H 'clientdata: sachin' \
  -H 'content-type: multipart/form-data;' \
  -H 'postman-token: ed70d17c-ecf6-66c7-619e-85eac7d62803' \
  -F purchasID=23124212 \
  -F purchaserAmount=4320'

答案 18 :(得分:2)

对我来说问题更令人烦恼,我在服务中使用服务而忘记在appModule中添加它作为依赖项! 希望这可以帮助有人节省几个小时打破应用程序只是为了重新建立它

答案 19 :(得分:1)

就我而言,我试图扩展“ NativeDateAdapter”以覆盖“ format(date: Date, displayFormat: Object)”方法。

在AngularMaterial-2 DatePicker中。

所以基本上我忘了添加@Injectable注释。

将其添加到“ CustomDateAdapter”类后:

@Injectable({
  providedIn: 'root'
})

错误消失了。

答案 20 :(得分:1)

添加 Injectable 解决了我的问题:

错误代码

Set doc = CreateObject("Word.Application")

修复后

import { Observable } from 'rxjs';
import { io } from 'socket.io-client';
import { HttpClient } from '@angular/common/http';

export class Chat {

答案 21 :(得分:1)

对于Angle 6和更高版本,请尝试

@Injectable({
  providedIn: 'root'
})

..就在您的服务类上方,中间没有其他行

优势

  • 无需将服务添加到任何模块(将被“自动发现”)
  • 服务将是一个单例(因为它将被注入到根目录中)

[angular docs]

答案 22 :(得分:1)

就我而言,原因如下:

  • 我的可注射服务A扩展了另一类B
  • B的构造函数需要一个参数
  • 我没有在A中定义任何构造函数

因此,当尝试创建对象A时,默认构造函数失败。我不知道为什么这不是编译错误。

我通过在A中添加一个构造函数(它正确地称为B的构造函数)来解决此问题。

答案 23 :(得分:1)

虽然可能已经提到了来自桶内的导出类的排序,但以下情况也可能产生相同的效果。

假设您在A取决于BC的同一文件中导出了类ABC

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

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

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

由于依赖类(即本例中类BC)尚未为Angular所知,(可能在Angular&期间运行时#39;对类A 的依赖注入过程)引发错误。

解决方案

解决方案是在完成DI的类之前声明并导出依赖类。

即。在上面的例子中,类A在其依赖项定义后被声明:

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

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

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

答案 24 :(得分:1)

我通过错误输入服务名称遇到此错误,即构造函数(private myService:MyService )。

对于拼写错误的服务,我可以通过检查Chrome-&gt; Console中的页面来确定哪个服务是问题(我在构造函数中列出了几个)。您将通过显示对象Object,object Object,?作为消息的一部分看到“参数”数组列表。 (或类似的东西)。注意“?”的位置是,这是导致问题的服务的位置。

答案 25 :(得分:0)

就我而言,那是我升级到主要版本的TypeScript版本,以及我添加到某些Class属性中的赋值声明。

还原更改为我解决了这个问题。 (details here

答案 26 :(得分:0)

使用桶装进口时 - 请考虑首先导入注射剂作为经验法则。

答案 27 :(得分:0)

在我的情况下,添加“ emitDecoratorMetadata”和“ esModuleInterop”即可解决问题。

https://github.com/thymikee/jest-preset-angular/issues/288

答案 28 :(得分:0)

import {Injector} from '@angular/core';
import {ServiceA} from './service-a';

@Component({
  // ... 
})
class MyComp {
  constructor(private injector: Injector) {
     const serviceA = injector.get(ServiceA);
  }
}

答案 29 :(得分:0)

如果您尝试注入接口,也会发生此错误:

某处:

export const MY_SERVICE = new InjectionToken<MyService>('MY_SERVICE');

export interface MyService {
  // ...
}

@Injectable()
export class MyServiceImpl implements MyService {
  // ...
}

不正确:

  constructor(
    private myService: MyService
  ) {}

正确:

  constructor(
    @Inject(MY_SERVICE) private myService: MyService
  ) {}

答案 30 :(得分:0)

uguglar导入路径区分大小写。请在使用服务的所有位置检查服务路径是否正确,并在所有位置检查字母大小写是否正确和相同。

答案 31 :(得分:0)

在引用interface时也会发生这种情况。

更改interface class修复它,使用和不使用@Inject

答案 32 :(得分:0)

在某些情况下,错误是由于将@ angular-devkit / build-angular升级到〜0.803。*引起的。有关详细信息,请参见https://github.com/angular/angular-cli/issues/15892

答案 33 :(得分:0)

您可以尝试再次运行以下命令:

In May 2016, she was one of the 12 candidates nominated by the BJP to contest the Rajya Sabha elections due on 11 June 2016.

答案 34 :(得分:0)

在我的情况下,修复方法是将绝对路径替换为绝对路径 之前

import {Service} from './service';

之后

import {Service} from 'src/app/services/service';

看起来像打字稿/角度问题

答案 35 :(得分:0)

就我而言,我错过了调用我继承的类的构造函数的机会。

之前:

@Component({ ... })
export class ComponentA extends ComponentParent {
  // ...
}

之后:

@Component({ ... })
export class ComponentA extends ComponentParent {
  constructor(protected route: ActivatedRoute, protected store$: Store<AppState>) {
    super(route, store$);
  }
  // ...
}

答案 36 :(得分:0)

对我来说,停止应用程序并发布服务可以解决问题

答案 37 :(得分:0)

就我而言,我是从同一个组件文件中导出一个Class和一个Enum:

mComponent.component.ts

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

然后,我试图使用来自MyEnum的孩子的MyComponentClass。这导致无法解决所有参数错误

MyEnum移到MyComponentClass的单独文件夹中,这解决了我的问题!

正如GünterZöchbauer所说,这是因为服务或组件与循环有关。

答案 38 :(得分:0)

陷阱!

如果以上答案均不能帮助您,则可能是您从组件正在注入服务的同一个文件中导入了某些元素。

我的解释更好:

这是服务文件

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

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

这是组件文件

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

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

因此,即使符号不在同一组件内,而在同一文件内,也会导致问题。将符号(可以是函数,常量,类等)移动到其他位置,错误就会消失

答案 39 :(得分:0)

由于错误反馈不足,这可能是一个很难调试的问题。如果您担心实际的循环依赖关系,这是在堆栈跟踪中查看的最重要的内容a)服务的名称b)该服务中带有问号的构造函数参数,例如如果看起来像这样:

  

无法解析AuthService的所有参数:([[Object Object],   [对象对象],[对象对象],[对象对象],?)

则表示第5个参数是也依赖AuthService的服务。即问号,表示DI并没有解决它。

从那里,您只需要通过重组代码来分离这两个服务。

答案 40 :(得分:0)

This answer对于此问题可能很有帮助。另外,就我而言,将服务导出为default是原因。

错误:

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

正确:

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

答案 41 :(得分:0)

有时在app.module.js中声明Angular的内置模块(HttpClientModule,HttpErrorResponse等)时会发生这种情况。我也遇到了同样的问题,但现在已经解决了。

我犯的错误是将HttpClientModule提到提供商而不是导入的角度模块

答案 42 :(得分:0)

就我而言,这是一个循环引用。 我有MyService呼叫Myservice2 然后MyService2调用MyService。

不好:(

答案 43 :(得分:0)

如果在与组件(使用它的组件)相同的文件中定义了服务,并且在文件中的组件之后( )定义了服务,则可能会出现此错误。这是由于其他人提到的相同“ forwardRef”问题造成的。目前,VSCode不太适合向您显示此错误,并且编译成功。

使用--aot运行构建可以掩盖此问题,这是由于编译器的工作方式(可能与摇树有关)。

解决方案:请确保该服务是在另一个文件中定义或在组件定义之前定义的。 (我不确定在这种情况下是否可以使用forwardRef,但是这样做似乎很笨拙。)

如果我有一个非常简单的服务,该服务与组件紧密相连(有点像视图模型),例如。 ImageCarouselComponent,我可以将其命名为ImageCarouselComponent.service.ts,这样它就不会与我的其他服务混为一谈。

答案 44 :(得分:0)

就我而言,我对没有依赖性的服务具有依赖性,因此没有向服务类添加constructor()函数。我在依赖服务类中添加了无参数构造函数,一切开始正常工作。

答案 45 :(得分:0)

对我而言,这是因为我在尝试加快编译时间时停止使用-aot标志。

 ng serve -aot

答案 46 :(得分:0)

对我来说,这是因为我的@Component装饰器和我的Component类之间有一条空行。这导致装饰器无法应用于该类。