You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular报错InjectionToken无提供者,组件已配置providers的原因及解决

Angular报错:No provider for InjectionToken bar! 原因及解决方法

问题场景

现有以下代码:

FooService 代码

import { inject, Injectable, InjectionToken } from '@angular/core';

export const Bar = new InjectionToken<string>('bar');

@Injectable({ providedIn: 'root' })
export class FooService {
  bar = inject(Bar);

  getSome() {
    console.log({ bar: this.bar });
  }
}

AppComponent 代码

import { Component, VERSION } from '@angular/core';
import { Bar, FooService } from './foo.service';

@Component({
  selector: 'my-app',
  template: `in app`,
  standalone: true,
  providers: [{ provide: Bar, useValue: 'blabla' }],
})
export class AppComponent {
  name = 'Angular ' + VERSION.major;

  constructor(private fooService: FooService) {}

  some() {
    this.fooService.getSome();
  }
}

运行后抛出错误:

No provider for InjectionToken bar!

报错原因

核心原因是注入器层级不匹配:

  • FooService通过providedIn: 'root'声明,属于根注入器管理的单例服务,会在应用启动时由根注入器创建。
  • 组件的providers配置属于组件注入器层级,根注入器无法访问组件注入器中的依赖项。
  • 当根注入器创建FooService时,找不到Bar的提供者,因此抛出错误。

解决方法

方案一:将Bar提升到根注入器

把Bar的提供者配置到根注入器层级,让FooService所在的根注入器能找到它。例如在main.ts中配置:

import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { Bar } from './app/foo.service';

bootstrapApplication(AppComponent, {
  providers: [{ provide: Bar, useValue: 'blabla' }]
});

方案二:让FooService归属于组件注入器

移除FooService的providedIn: 'root'配置,将其添加到组件的providers中,使FooService与Bar处于同一注入器层级:

// 修改FooService
import { inject, Injectable, InjectionToken } from '@angular/core';

export const Bar = new InjectionToken<string>('bar');

@Injectable() // 去掉providedIn: 'root'
export class FooService {
  bar = inject(Bar);

  getSome() {
    console.log({ bar: this.bar });
  }
}

// 修改AppComponent的providers
@Component({
  selector: 'my-app',
  template: `in app`,
  standalone: true,
  providers: [
    FooService, // 添加FooService到组件提供者
    { provide: Bar, useValue: 'blabla' }
  ],
})
export class AppComponent {
  name = 'Angular ' + VERSION.major;

  constructor(private fooService: FooService) {}

  some() {
    this.fooService.getSome();
  }
}

方案三:使用组件注入器手动获取服务(可选)

如果需要更灵活的控制,可以在组件中通过Injector手动获取FooService,确保使用组件注入器实例:

import { Component, VERSION, Injector } from '@angular/core';
import { Bar, FooService } from './foo.service';

@Component({
  selector: 'my-app',
  template: `in app`,
  standalone: true,
  providers: [{ provide: Bar, useValue: 'blabla' }],
})
export class AppComponent {
  name = 'Angular ' + VERSION.major;
  private fooService: FooService;

  constructor(private injector: Injector) {
    this.fooService = injector.get(FooService);
  }

  some() {
    this.fooService.getSome();
  }
}

注意:此方案需要同时移除FooService的providedIn: 'root',并将其添加到组件providers中。


内容的提问来源于stack exchange,提问作者Jon Sud

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 19:50:26