Angular服务注入问题:@Injectable不起作用,但是提供者可以

时间:2018-07-27 19:43:56

标签: angular angular6

我通过SO进行了扫描,但是看似奇怪的问题却什么也找不到。我将首先复制一些代码以提供上下文:

我的服务:

import { Injectable } from '@angular/core';

import { MyModule } from './my.module';

@Injectable({
  providedIn: MyModule,
})
export class ApiService {

  // router: Router;

  constructor() {
    // this.router = MyModule.injector.get(Router);
  }
... Some methods ...
}

我的模块:

import { NgModule, Injector } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { ConnectionsListComponent } from './connections-list/connections-list.component';
import { StoreModule } from '@ngrx/store';
import * as fromMy from './reducers';
import { routes } from './routes';
... component imports ...

@NgModule({
  imports: [
    CommonModule,
    RouterModule.forChild(routes),
    StoreModule.forFeature('my', fromMy.reducers),
  ],
  declarations: [ConnectionsListComponent, MyShellComponentComponent, DashboardContainerComponent, DashboardElementComponent, DashboardElementInfoItemComponent],
  // providers: [ApiService]
})
export class MyModule {

  constructor() {

  }
}

我的组件:

import { Component, OnInit, Input } from '@angular/core';
import { AttributeArrayHelperService } from '../attribute-array-helper.service';
import { ApiService } from '../api.service';

.. some interfaces ...

@Component({
  selector: 'vz-dashboard-element',
  templateUrl: './dashboard-element.component.html',
  styleUrls: ['./dashboard-element.component.scss']
})
export class DashboardElementComponent implements OnInit {

  @Input() element: ElementInterface;
  @Input() erpType: String;

  equipmentAttributes: Object[] = []

  workOrderAttributes: Object[] = [

  ];

  constructor(private apiService: ApiService) {

   }

  ngOnInit() {
    const helper = new AttributeArrayHelperService();
    console.log(this.element);
    const lookupValues = helper.parseObjectArrayFor(this.element.Attributes, ['1', '2', '3']);
    console.log(lookupValues);
    const showValues = helper.parseArrayNames(lookupValues);
    console.log(showValues);
    console.log(this.apiService);
    console.log(this.apiService.getDashboardEntityInformation('4', '5', '6'));
    showValues.push();
    this.equipmentAttributes = showValues;
  }
}

好,所以现在这里是我的问题:当我尝试使用上面的@Injectable时,在声明了模块的情况下,我在浏览器中收到以下错误,但没有TS编译错误(有不过是循环引用警告):

  

DashboardContainerComponent.html:2错误错误:   StaticInjectorError(AppModule)[DashboardElementComponent->   ApiService]:StaticInjectorError(平台:   核心)[DashboardElementComponent-> ApiService]:       NullInjectorError:没有ApiService的提供程序!

当我将其更改为使用@Injectable()并取消对提供程序的注释时,它似乎很喜欢,并且一切都很好。我只是好奇为什么会这样?通过阅读6.1的Angular文档,这似乎可以满足需要。

有关更多信息,它们全部在子模块中,并且该服务与该模块隔离。在这一点上,我只是迷失了自己所缺少的东西,并且是我办公室中的少数JS人员之一,并且是唯一使用Angular的人,我没有另一双眼睛可以帮助我识别自己我不见了。

在此方面的任何帮助都得到了极大的赞赏,因为这已经困扰了我几天。预先感谢,

史蒂夫

编辑:另外要注意的是,这是一个从5升级到6的应用程序。我按照指南进行了操作,使它全部正常工作,所以也许它来自升级?

1 个答案:

答案 0 :(得分:0)

因此,在进一步研究此问题和功能之后,我发现我不是唯一遇到此问题的人,并且这似乎是由于对文档的误解造成的。正如此处所引用的:GitHub Angular CLI Issue 10170,尽管该功能的文档似乎会告诉您其他方式,但我这样做的方式是错误的。

从本质上讲,它正在创建导入循环,而TS正在尽其所能避免此类问题。现在推荐的使用@Injectable()的方法是与{ providedIn: 'root' }一起使用,这使得可注入服务在应用程序的根级别可用。话虽这么说,但如果它在多个模块或根模块中使用,它似乎只会捆绑在顶层。如果该服务仅在单个子模块中使用,它将与该子模块捆绑在一起。

我的解决方案是更改为

@Injectable({
  providedIn: 'root',
})

关于我的新服务,其余的我留在各自模块的模块定义的providers数组中。至少直到不再支持providers为止,它们都可以很好地协同工作,届时我会将它们全部转换为这种新格式。