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
相关产品推荐
相关产品推荐

