我已经用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函数中有服务,所以它有一个提供者。而且我似乎能够将它注入到任何其他组件的构造函数中而没有任何问题。


当前回答

错误#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 { ... }

其他回答

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

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

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

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

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

之前:

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

后:

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

对我来说,当我错误地在填充中禁用此导入时,我得到了这个错误。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';

明白了!

如果以上答案都对您没有帮助,那么您可能正在从组件注入服务的同一个文件中导入某个元素。

我解释得更好:

这是服务文件:

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

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

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

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

因此,我有以下建议:

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