【问题标题】:NullInjectorError: No provider for HttpHandler! despite HttpClient/HttpClientModule being presentNullInjectorError:没有 HttpHandler 的提供者!尽管存在 HttpClient/HttpClientModule
【发布时间】:2018-12-27 15:44:22
【问题描述】:

我是一个基于 Angular 的 UI 项目的新手,我使用 vscode 生成了两个新组件以供项目使用。但是,每当我将更改推送到 git(bitbucket) 时,我都会不断收到错误,而当我在我的机器上构建项目时,这些错误并不存在。我需要在哪里提供 HttpClient/HttpClientModule 以便这些新组件可以使用 HttpHandler?

我在 app.module.ts 和新组件本身上都添加了 HttpClientModule 和 HttpClient 的提供程序。

modal-wiped-all.component.ts

import { Component, OnInit } from '@angular/core';
import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { Router } from '@angular/router';

import { OrganisationsApiService } from 'src/app/api/organisations/organisations-api.service';
import { HttpClient, HttpClientModule, HttpHandler } from '@angular/common/http';


@Component({
  selector: 'app-modal-wipedall',
  templateUrl: './modal-wiped-all.component.html',
  providers: [NgbActiveModal,
  OrganisationsApiService,
  HttpClientModule,
HttpClient,
]})

cleanup.component.ts

import { Component, OnInit } from '@angular/core';
 import { HttpClient, HttpClientModule, HttpHandler } from '@angular/common/http';
import { OrganisationsApiService } from 'src/app/api/organisations/organisations-api.service';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';

import { ModalWipedAllComponent } from '../modal/modal-wiped-all/modal-wiped-all.component';



@Component({
  selector: 'app-cleanup',
  templateUrl: './cleanup.component.html',
  styleUrls: ['./cleanup.component.css'],
  providers: [OrganisationsApiService,
    NgbModal,
    HttpClientModule,
    HttpClient,

  ]
})


export class CleanupComponent implements OnInit {

  submitted: boolean;
  loading: boolean;
  deleted: number;

  constructor(
    private http: HttpClient,
    private api: OrganisationsApiService,
    private modalService: NgbModal) {

   }

app.module.ts 提供者

providers: [AwsApiService,
              OrganisationsApiService,
              LabsApiService,
              UsersApiService,
              UserManagementDataService,
              ConfigDataService,
              ErrorDataService,
              DeploymentResponseDataService,
              ModalOptionsComponent,
              ModalConfigurationComponent,
              ModalUndeployLabComponent,
              ModalCreatedUserComponent,
              NgbActiveModal,
              HttpClientModule,
              HttpClient,


     { provide: HTTP_INTERCEPTORS,
      useClass: HttpRequestInterceptor,
      multi: true}
    ],   

错误信息:

CleanupComponent.CleanupComponent should createChrome 56.0.2924 (Linux 0.0.0)
<1s
Error: StaticInjectorError(DynamicTestModule)[HttpClient -> HttpHandler]: 
  StaticInjectorError(Platform: core)[HttpClient -> HttpHandler]: 
    NullInjectorError: No provider for HttpHandler!
    at NullInjector.push../node_modules/@angular/core/fesm5/core.js.NullInjector.get node_modules/@angular/core/fesm5/core.js:1062:1)
    at resolveToken node_modules/@angular/core/fesm5/core.js:1300:1)
    at tryResolveToken node_modules/@angular/core/fesm5/core.js:1244:1)
    at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get node_modules/@angular/core/fesm5/core.js:1141:1)
    at resolveToken node_modules/@angular/core/fesm5/core.js:1300:1)
    at tryResolveToken node_modules/@angular/core/fesm5/core.js:1244:1)
    at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get node_modules/@angular/core/fesm5/core.js:1141:1)
    at resolveNgModuleDep node_modules/@angular/core/fesm5/core.js:8369:1)
    at NgModuleRef_.push../node_modules/@angular/core/fesm5/core.js.NgModuleRef_.get node_modules/@angular/core/fesm5/core.js:9057:1)
    at resolveDep node_modules/@angular/core/fesm5/core.js:9422:1)




ModalWipedAllComponent.ModalWipedAllComponent should createChrome 56.0.2924 (Linux 0.0.0)
<1s
Error: StaticInjectorError(DynamicTestModule)[HttpClient -> HttpHandler]: 
  StaticInjectorError(Platform: core)[HttpClient -> HttpHandler]: 
    NullInjectorError: No provider for HttpHandler!
    at NullInjector.push../node_modules/@angular/core/fesm5/core.js.NullInjector.get node_modules/@angular/core/fesm5/core.js:1062:1)
    at resolveToken node_modules/@angular/core/fesm5/core.js:1300:1)
    at tryResolveToken node_modules/@angular/core/fesm5/core.js:1244:1)
    at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get node_modules/@angular/core/fesm5/core.js:1141:1)
    at resolveToken node_modules/@angular/core/fesm5/core.js:1300:1)
    at tryResolveToken node_modules/@angular/core/fesm5/core.js:1244:1)
    at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get node_modules/@angular/core/fesm5/core.js:1141:1)
    at resolveNgModuleDep node_modules/@angular/core/fesm5/core.js:8369:1)
    at NgModuleRef_.push../node_modules/@angular/core/fesm5/core.js.NgModuleRef_.get node_modules/@angular/core/fesm5/core.js:9057:1)
    at resolveDep node_modules/@angular/core/fesm5/core.js:9422:1)

我希望项目能够像在本地一样构建,但我得到的是 NullInjectorErrors

更新:component.spec.ts 文件 模态擦除全部

import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { ModalWipedAllComponent } from './modal-wiped-all.component';

describe('ModalWipedAllComponent', () => {
  let component: ModalWipedAllComponent;
  let fixture: ComponentFixture<ModalWipedAllComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ ModalWipedAllComponent ]  
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(ModalWipedAllComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

清理组件

import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { CleanupComponent } from './cleanup.component';

describe('CleanupComponent', () => {
  let component: CleanupComponent;
  let fixture: ComponentFixture<CleanupComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ CleanupComponent ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(CleanupComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

【问题讨论】:

  • 你不必提供HttpClient,只要HttpClientModule就够了。此外,您不需要在每个组件中单独提供。如果您已在 root 中提供,它将可用于完整的应用程序
  • 我在各处都提供了 HttpClient 模块,试图修复错误。它在根模块 app.module.ts 中提供,并在同一个 app.module.ts 文件中正确导入。然而错误仍然存​​在。
  • 在提供任何服务之前提供 HttpClientModule。顺序很重要。最好的位置是把它放在 app.module.ts 的导入数组中 BrowserModule 之后
  • @CallumMartin 检查我的答案。我已经给出了步骤。
  • 现在注意到了.. 您已将 HttpClientModule 放在提供程序中。你不必那样做。你必须把它放在imports 数组中。

标签: angular angular6


【解决方案1】:

有几个步骤可以实现这一点 -

  1. 在您的 app.module.ts 中导入 HttpClientModule 如下所示

    从 '@angular/common/http' 导入 { HttpClientModule };

并使用@NgModuleimports 数组,如下所示。

@NgModule({
 ...
 imports : [BrowserModule,HttpClientModule],  
 providers: [.... other services ..]
 })

HttpClientModule 应该加在 BrowserModule 之后。此顺序在 imports 数组中很重要。

  1. 从组件中删除所有 HttpClientModule 的导入。如果您在根模块中导入它就足够了。

  2. 从 app.module.ts 中 @NgModuleproviders 数组中删除 HttpClient,这不是必需的。可以直接在组件的构造函数中注入 HttpClient 的实例,而不需要在提供者中添加。

  3. 如果你使用ng-bootstrap,那么你只需要像下面这样在你的 app.module.ts 中导入它 - import {NgbModule} from '@ng-bootstrap/ng-bootstrap';

然后像下面这样使用它

@NgModule({
     ...
     imports : [BrowserModule,HttpClientModule,NgbModule.forRoot()],
     providers: [.... other services ..]
     })

NgbActiveModal 不需要添加到提供者中。

更新:您还需要在您的规范文件中导入HttpClientModule 模块以进行单元测试。 Testbed 创建一个测试模块来测试你的组件。由于您在组件的构造函数中注入了 OrganisationsApiService,因此您需要将其添加到 testbed 模块的 providers 数组中,如下所示。

这是CleanupComponent的spec文件的代码-

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { HttpClientModule } from '@angular/common/http';
import { CleanupComponent } from './cleanup.component';
import { OrganisationsApiService } from 'src/app/api/organisations/organisations-api.service';

describe('CleanupComponent', () => {
  let component: CleanupComponent;
  let fixture: ComponentFixture<CleanupComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ CleanupComponent ],
      imports : [HttpClientModule],
      providers : [OrganisationsApiService ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(CleanupComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

同样,您需要对 ModalWipedAll 的其他规范文件进行更改

【讨论】:

  • 对代码进行了一些调整后,我仍然得到这个错误:错误:StaticInjectorError(DynamicTestModule)[CleanupComponent -> HttpClient]: StaticInjectorError(Platform: core)[CleanupComponent -> HttpClient]: The这里唯一的区别是 HttpClientModule 在提供者和导入列表中的位置较高,与 HttpClient 一样
  • 什么是 DynamicTestModule?它是您使用 TestBed 的单元测试文件的一部分吗?你能把它的代码贴出来吗?
  • @CallumMartin 你能贴出 DynamicTestModule 的代码吗
  • 我认为 dynamicTestModule 是一个内置的有角度的东西,我的 spec.ts 文件中没有它的代码。我已经添加了这些以供参考,以防它们成为问题。谢谢。
  • @CallumMartin 我已经更新了我的答案。您还需要将模块导入到 TestBed.configureTestingModule
【解决方案2】:

如果您使用 Jasmine 和 Karma 通过 ng test 进行单元测试,那么您可能需要在 spec 文件中导入 HttpClientTestingModule。

【讨论】:

  • 如果有人在此处查看此答案的代码部分,请在您的 spec.ts 文件中 import { HttpClientTestingModule } from '@angular/common/http/testing'; beforeEach(() => { TestBed.configureTestingModule({ imports: [HttpClientTestingModule], }); });
猜你喜欢
  • 2019-06-25
  • 1970-01-01
  • 1970-01-01
  • 2019-11-16
  • 2021-01-20
  • 2018-09-19
  • 2018-05-02
  • 2020-12-25
  • 1970-01-01
相关资源
最近更新 更多