尝试向angular组件注入服务时出错“EXCEPTION: Can't resolve all parameters for component”,为什么?

我已经用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);
}


}

我在浏览器控制台得到的错误是这样的:

EXCEPTION:不能解析HeaderComponent:(?)的所有参数。

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

449407 次浏览

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

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

它也应该可以通过改变桶中的出口顺序来修复(不知道细节,但也提到了)

如前所述,这个问题是由桶内的导出排序引起的,而桶内的导出排序是由循环依赖关系引起的。

更详细的解释在这里:https://stackoverflow.com/a/37907696/893630

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

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

我就此事发表了一期文章

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

我认为这种快速失败是件好事,因为无论如何都应该避免。如果您希望您的服务更加模块化和可重用,最好尽可能避免循环引用。这个帖子突出了围绕它的陷阱。

因此,我有以下建议:

  • 如果你觉得类的交互太频繁(我说的是功能嫉妒),你可能会考虑将两个服务合并到一个类中
  • 如果上面的方法对你不起作用,考虑使用3日服务 (EventService),两个服务都可以注入它来交换消息。

从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手动:ForwardRef . href="https://angular.io/docs/js/latest/api/core/index/forwardRef-function.html" rel="noreferrer">

Angular 2中的前向引用 .

好吧,对我来说,这个问题甚至更烦人,我正在使用服务中的服务,忘记在appModule中添加它作为依赖项! 希望这能帮助一些人节省几个小时的应用程序分解,只是重新建立它

我在输入服务名称时遇到了这个错误,即构造函数(private myService: myService)。

对于拼写错误的服务,我能够通过检查Chrome->控制台中的页面来确定哪个服务是问题(我在构造函数中列出了几个)。您将看到作为消息的一部分的“参数”数组列表显示对象对象,对象对象,?(或者类似的事情)。请注意“?”在哪里,这是引起问题的服务的位置。

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

例如,这会产生Can't resolve all parameters for MyHttpService错误。

Injectable()
export class MyHttpService{
}

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

@Injectable()
export class MyHttpService{
}

从可注入的constructor()方法中删除参数解决了这个问题。

如果服务一个依赖于服务B静态属性/方法,而服务B本身依赖于服务一个槽依赖注入,则会出现此错误。所以这是一种循环依赖,尽管它不是,因为属性/方法是静态的。可能是与AOT一起出现的错误。

当使用桶导入时,作为经验法则,首先考虑导入注射剂。

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

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

你必须在@Component decorator中或在组件声明的模块中添加providers数组。在组件内部,你可以这样做:

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

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

我犯的错误是把HttpClientModule提到了angular Module的供应商而不是进口

在我的例子中,发生这种情况是因为我没有声明构造函数形参的类型。

我有这样的东西:

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

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

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

除了缺少@Injectable()装饰器之外

抽象类中缺少@Injectable()装饰器导致不能解析服务的所有参数:(?) 装饰器需要出现在MyService中以及派生类BaseService

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


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

错误# 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:小写的“i”:

//Uncaught ReferenceError: injectable is not defined
@injectable
export class MyFooService { ... }
错误# 5:你忘记了: import {Injectable} from '@angular/core'

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

正确的:

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

在我的例子中,将错误的参数传递给构造函数会产生这个错误,关于这个错误的基本思想是,你在不知不觉中传递了一些错误的参数给任何函数。

export class ProductComponent {
productList: Array<Product>;


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

我通过去掉这个参数来解决这个问题。

对我来说,这是因为我停止使用-aot标志,同时试图使编译时间更快。

 ng serve -aot

虽然前面已经提到了从桶中导出类的订购,但下面的场景也可能产生相同的效果。

假设你有ABC类从同一文件中导出,其中A依赖于BC:

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


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


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

由于Angular还不知道依赖类(即在本例中是BC类),因此(可能是在Angular在A类上的依赖注入过程的运行时)会引发错误。

解决方案

解决方案是在执行DI的类之前声明和导出依赖类。

例如,在上面的例子中,类A是在它的依赖关系定义之后声明的:

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


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


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

对我来说,这是因为我的@Component装饰器和Component类之间有一个空行。这导致装饰器没有应用到类中。

另一种可能是在tsconfig.json中没有将emitDecoratorMetadata设置为true

{
"compilerOptions": {


...


"emitDecoratorMetadata": true,


...


}


}

在我的例子中,我从同一个组件文件中导出了一个类和一个Enum:

mComponent.component.ts:

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

然后,我试图从MyComponentClass的子对象中使用MyEnum。这导致不能解决所有参数错误

通过移动MyEnum在一个单独的文件夹从MyComponentClass,这解决了我的问题!

正如Günter Zöchbauer提到的,这是因为服务或组件是循环依赖的。

在我的例子中,我需要将import "core-js/es7/reflect";添加到我的应用程序中,以使@Injectable工作。

对我来说,这只是@Injectable缺少()。正确的是@Injectable()

在我的情况下,这是因为插件Augury,禁用它将工作得很好。替代选项是aot,也工作。

所有功劳都归功于@Boboss74,他在这里发布了答案:https://github.com/angular/angular/issues/23958

对我来说,当我在腻子中< em >错误地禁用< / em >这个导入时,我得到了这个错误。Ts文件,您需要确保它被导入以避免该错误。

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

在我的例子中,我对一个没有依赖关系的服务进行了依赖,因此我没有向服务类添加constructor()函数。我向依赖的服务类添加了一个无参数构造函数,一切都开始工作了。

在我的情况下,我试图扩展“NativeDateAdapter”,以覆盖“format(date: Date, displayFormat: Object)”方法。

在AngularMaterial-2 DatePicker中。

所以基本上我忘记添加@Injectable表示法。

在我把这个添加到我的“CustomDateAdapter”类后:

@Injectable({
providedIn: 'root'
})

错误已经消失了。

如果你的服务与使用它的组件定义在同一个文件中,并且服务定义为(文件中的组件),你可能会得到这个错误。这是由于其他人提到的相同的“forward dref”问题。此时,VSCode并不能很好地向您显示这个错误,并且构建编译成功。

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

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

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

在我的例子中,这是一个循环引用。 我让MyService调用Myservice2 和MyService2调用MyService.

不太好:(

就我而言,原因如下:

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

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

我通过在a中添加一个构造函数来解决这个问题,它正确地调用了B的构造函数。

这个答案可能对这个问题很有帮助。此外,在我的例子中,将服务导出为default是原因。

错误的:

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

正确的:

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

由于错误中缺乏反馈,这可能是一个非常难以调试的问题。如果你关心一个实际的循环依赖,这里是在堆栈跟踪中最重要的东西:a)服务的名称;b)该服务中带有问号的构造函数参数,例如,如果它看起来像这样:

不能解析AuthService的所有参数:([object object], [object object], [object object], [object object], ?)

那么它意味着第五个参数也是一个依赖于AuthService的服务。即问号,表示未被DI解决。

从这里开始,您只需要通过重新构造代码来解耦这两个服务。

明白了!

如果以上答案都对你没有帮助,也许你正在从同一个文件导入某个元素,其中组件正在注入服务。

我解释得更好:

这是服务文件:

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

因此,即使符号不在同一个组件中,而只是在同一个文件中,也会引起问题。将符号(可以是函数、常量、类等等)移动到其他地方,错误就会消失

在我的例子中,这是我升级到主版本的TypeScript版本,以及我添加到一些Class属性中的赋值断言。

恢复更改为我解决了这个问题。(细节)

对我来说,停止应用程序并发出ng服务解决了这个问题

在我的例子中,我错过了调用我继承的类的构造函数。

之前:

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

后:

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

在我的情况下修复是替换相对路径与绝对 在< / p >

import {Service} from './service';

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

看起来是typescript/angular的问题

您可以重试执行如下命令:

ng serve --open

在可能的情况下,错误是由升级@angular-devkit/build-angular到~0.803.*引起的。详细信息见https://github.com/angular/angular-cli/issues/15892

对于angular 6和更新的版本,请尝试

@Injectable({
providedIn: 'root'
})

..就在你的服务等级上面,中间没有其他线

优势

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

(角文档)

导入路径是区分大小写的。检查您使用服务的所有地方的服务路径是否正确,并检查所有地方的字母大小写是否正确且相同。

如果你试图注入一个接口,也会发生这个错误:

的地方:

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

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


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

我的情况,添加"emitDecoratorMetadata"和“;esModuleInterop"解决了问题。

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

添加Injectable解决了我的问题:

错误代码

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


export class Chat {

修复后

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


@Injectable()
export class Chat {

问题是模块中的元素对于属于同一模块的元素应该使用相对进口;它们永远不应该通过模块的公共API桶(或一般的桶)导入。

该导入的问题是,如果依赖于服务的某些东西首先在桶中加载(直接或不直接),那么DI系统将失败,因为服务还没有声明,因此无法解决。

尝试从绝对更改导入:

import { UserService } from 'src/app/users/user.service';

相对:

import { UserService } from '../../users/user.service';

我试了这里给出的几乎所有答案,但没有一个对我有帮助。

对我有用的是在Visual Studio Code中关闭项目,打开文件资源管理器,进入我的项目并删除dist文件夹。

然后我对所有库进行了每个构建,然后在npm start中重新运行项目。