首页 文章

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

提问于
浏览
301

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

30 回答

  • 23

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

  • 16

    除了缺少 @Injectable() 装饰器

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

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

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

    mComponent.component.ts

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

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

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

    正如GünterZöchbauer所提到的,这种情况正在发生,因为服务或组件是循环依赖的 .

  • 5

    尽管可能已经提到了来自桶内的导出类的排序,但是以下场景也可以产生相同的效果 .

    假设您从 A 依赖于 BC 的同一文件中导出了类 ABC

    @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) {}
    }
    
  • 0

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

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

    Injectable()
    export class MyHttpService{
    }
    

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

    @Injectable()
    export class MyHttpService{
    }
    
  • 0

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

  • 7

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

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

  • 37

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

    我有这样的事情:

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

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

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

    对我来说,当我在polyfills.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';
    
  • 0

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

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

    I opened an issue on this matter .

  • 353

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

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

    WRONG #1: 忘记装饰者:

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

    WRONG #2: 省略"@"符号:

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

    WRONG #3: 省略"()"符号:

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

    WRONG #4: 小写"i":

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

    WRONG #5: 你忘了: import from '@angular/core';

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

    CORRECT:

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

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

    就个人而言, I am glad that this fails fast as it should probably be avoided anyway . 如果您希望您的服务更加模块化/可重复使用,最好尽可能避免循环引用 . 这个post强调了周围的陷阱 .

    因此,我有以下建议:

    • 如果你觉得这些类经常交互(我说的是feature envy),你可能要考虑 merging the 2 services into 1 class .

    • 如果上述方法不适合您,请考虑使用 3rd serviceEventService ),两个服务都可以注入以便交换消息 .

  • 4

    对我来说问题更令人讨厌,我在服务中使用服务而忘记将其添加为appModule中的依赖项!希望这有助于有人节省几个小时打破应用程序,只是为了重新 Build 它

  • 6

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

  • 4

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

    我做的错误是将HttpClientModule提到 Providers 而不是 Import of angular Module

  • 2

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

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

  • 0

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

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

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

  • 0

    如果您的服务 A 依赖于 static property / method 服务 B 而服务 B 本身依赖于服务 A 通过依赖注入,则会出现此错误 . 所以它's a kind of a circular dependency, although it isn' t因为属性/方法是静态的 . 可能是与 AOT 结合发生的错误 .

  • 1

    如果您的服务在与组件相同的文件中定义(使用它),并且该服务是在文件中的组件之后定义的,则可能会出现此错误 . 这是由于其他人提到的同一个问题 . 此时VSCode不能很好地向您显示此错误并且构建成功编译 .

    由于编译器的工作方式(可能与树抖动有关),使用 --aot 运行构建可能会掩盖此问题 .

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

    如果我有一个非常简单的服务,它与一个组件(有点像视图模型)紧密相关 - 例如 . ImageCarouselComponent ,我可以将其命名为 ImageCarouselComponent.service.ts ,因此它不会与我的其他服务混淆 .

  • 1

    在我的情况下,这是因为插件Augury,禁用它将工作正常 . 替代选项是aot,也有效 .

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

  • 2

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

  • 3

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

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

  • 5

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

    {
      "compilerOptions": {
    
         ...
    
        "emitDecoratorMetadata": true,
    
         ...
    
        }
    
    }
    
  • 0

    在我的情况下,我试图扩展“ NativeDateAdapter " in order to override " format(date: Date, displayFormat: Object) ”方法 .

    在AngularMaterial-2 DatePicker中 .

    所以基本上我忘了添加 @Injectable anotation .

    将此添加到我的“CustomDateAdapter”类后:

    @Injectable({
      providedIn: 'root'
    })
    

    错误消失了 .

  • 0

    从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

  • 2

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

  • 1

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

  • 15

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

    export class ProductComponent {
        productList: Array<Product>;
    
        constructor(productList:Product) { 
             // productList:Product this arg was causing error of unresolved parameters.
             this.productList = [];
        }
    }
    

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

  • 246

    就我而言,它是一个循环引用 . 我让MyService调用Myservice2和MyService2调用MyService .

    不好 :(

相关问题