Angular DI错误 - EXCEPTION:无法解析所有参数

Kei*_*tto 389 angular2-di angular

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

}
Run Code Online (Sandbox Code Playgroud)

它拒绝使用的组件:

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

}
Run Code Online (Sandbox Code Playgroud)

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

EXCEPTION:无法解析HeaderComponent的所有参数:(?).

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

Gün*_*uer 419

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

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

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

  • 如果你有一个注入另一个服务的服务,那么这是正确的,第一个服务需要首先进入桶中. (16认同)
  • 由于存在很多这样的问题,Angular2团队不再推荐使用桶.很高兴听到我可以帮忙:) (16认同)
  • 不知道Angular 2团队不推荐使用桶装.如果是这样,他们应该注意在[词汇表](https://angular.io/docs/ts/latest/guide/glossary.html)中讨论他们的好处.像[angular2-webpack-starter](https://github.com/AngularClass/angular2-webpack-starter)这样的项目不应该使用它们. (12认同)
  • 它的缝合是固定的(不是`2.0.2`中的问题).我发现桶仍然有用,特别是当我需要在不同模块之间导入多个模型和服务时.这个来自'../../ shared/services'的`import {cleanValues,getState,FirebaseService,NotificationService,...};`当它不起作用时很痛苦(;`NgModule`对单例服务没有帮助) ... (3认同)
  • Argghh我通过更改桶(index.ts)文件中的导出顺序解决了它.非常感谢你 (3认同)
  • 我写了一篇关于这个问题的小文章,以防万一有人发现它有用:https://medium.com/@dSebastien/avoiding-import-issues-in-typescript-monorepos-d5a4b21f90ef (2认同)

J.P*_*rge 306

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

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

我在这个问题上提出了一个问题.

  • @osdamv哇,的确如此.好眼力. (4认同)

Rea*_*lar 101

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

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

export class HeaderComponent {
  mobileNav: boolean = false;

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

}
Run Code Online (Sandbox Code Playgroud)

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

参考

Angular 2手册:ForwardRef

Angular 2中的前向引用

  • GünterZöchbauer,我仍然试图找出我的代码的真正问题,但在此期间`forwardRef()`确实有助于摆脱`无法解决所有参数...'消息.至少该组件正在工作,而我正在寻找一个更好的问题解决方案.(是的,失败的依赖项直接从其文件导入) (4认同)
  • @GünterZöchbauer我用引用更新了我的答案.我不是想从你的答案中拿走,但这实际上解决了问题,人们需要了解它.如果你谷歌问题,没有结果说使用`forwardRef`.这很难找到.昨天花了我一整天来解决这个问题. (4认同)
  • `forwardRef()`已经存在于alpha ;-)只有在同一个文件中声明`Mobile`服务进一步声明时才需要它.如果类在不同的文件中,则不需要`forwardRef()` (3认同)
  • 如果有人对导入也迷路了:从“ @ angular / core”导入{Component,Inject,ForwardRefFn,forwardRef}; (2认同)

J.M*_*SON 60

错误#1:遗忘装饰者:

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

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

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

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

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

错误#4:小写"i":

//Uncaught ReferenceError: injectable is not defined
@injectable
export class MyFooService { ... }
Run Code Online (Sandbox Code Playgroud)

错误#5:你忘了: 从'@ angular/core'导入{Injectable};

//Uncaught ReferenceError: Injectable is not defined
@Injectable
export class MyFooService { ... }
Run Code Online (Sandbox Code Playgroud)

正确:

@Injectable()
export class MyFooService { ... }
Run Code Online (Sandbox Code Playgroud)


Mic*_*ael 25

如前所述,问题是由桶内的出口排序引起的,这是由循环依赖引起的.

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

  • 订购并没有解决我的问题。不使用桶。 (3认同)

Ste*_*aul 20

我也通过将服务A注入服务B而反之亦然.

我认为这很快就会失败,因为它应该可以避免.如果您希望您的服务更加模块化/可重复使用,最好尽可能避免循环引用.这篇文章突出了围绕这个的陷阱.

因此,我有以下建议:

  • 如果你觉得这些类经常交互(我说的是功能嫉妒),你可能会考虑将这两个服务合并为一个类.
  • 如果上述方法不适合您,请考虑使用第三项服务,(a EventService)两种服务都可以注入以便交换消息.


Hoc*_*eyJ 17

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

即产生Can't resolve all parameters for MyHttpService错误.

Injectable()
export class MyHttpService{
}
Run Code Online (Sandbox Code Playgroud)

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

@Injectable()
export class MyHttpService{
}
Run Code Online (Sandbox Code Playgroud)

  • 在我的例子中,我在@Injectable和服务类定义之间添加了额外的类和接口,因此服务类不再被标记为可注入. (2认同)

AJ *_*son 10

在我的情况下,我需要添加import "core-js/es7/reflect";到我的应用程序来进行@Injectable工作.


M K*_*M K 8

如果您的服务A依赖于服务B静态属性/方法而服务B本身依赖于服务A通过依赖注入,则会出现此错误.所以它是一种循环依赖,虽然它不是属性/方法是静态的.可能是与AOT结合发生的错误.


Bar*_*art 8

除了缺少@Injectable()装饰者

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

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

//MyService    
@Injectable()
export class MyService extends BaseService {
.....
}
Run Code Online (Sandbox Code Playgroud)


Alf*_*Moh 7

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

我有这样的事情:

constructor(private URL, private http: Http) { }
Run Code Online (Sandbox Code Playgroud)

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

constructor(private URL : string, private http: Http) {}
Run Code Online (Sandbox Code Playgroud)


oti*_*i10 7

这个答案可能对这个问题非常有帮助。此外,就我而言,default原因是导出服务。

错误的:

@Inject()
export default class MobileService { ... }
Run Code Online (Sandbox Code Playgroud)

正确的:

@Inject()
export class MobileService { ... }
Run Code Online (Sandbox Code Playgroud)


Ste*_*t_R 6

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

{
  "compilerOptions": {

     ...

    "emitDecoratorMetadata": true,

     ...

    }

}
Run Code Online (Sandbox Code Playgroud)


Mat*_*man 5

从injectable constructor()方法中删除参数解决了我的情况.


rep*_*epo 5

对我来说,只是缺少()@Injectable.适当的是@Injectable()


Tin*_*ang 5

就我而言,这是因为插件 Augury,禁用它会正常工作。替代选项是 aot,也有效。

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