Angular为Injectable服务提供InjectionToken报NullInjectorError如何解决
问题原因
报错来自两个配置错误,本质是Angular依赖注入的层级和注册规则不匹配:
- 服务注册层级错位
你给SharedService加了@Injectable({providedIn: 'root'})装饰器,这会把服务直接注册到全局根注入器,应用启动时根注入器就会尝试解析它的所有依赖。但API_REQUESTS这个注入令牌的提供者,是在业务模块里通过ApiModule.forRoot([])注册的:如果这个业务模块是懒加载模块,它的提供者会被挂在懒加载模块自己的子注入器上,根注入器没有权限访问子注入器的内容,自然找不到对应的令牌。
同时你在业务模块的providers数组里又重复声明了一次SharedService,这会额外生成一个服务实例,本身就违背了共享服务单例的设计预期。 forRoot()方法使用位置错误
Angular 中forRoot()是约定俗成的全局配置方法,只能在根模块(AppModule)调用一次,用来注册全局单例的服务、配置令牌。你在业务模块调用forRoot(),会直接导致提供者注册的层级混乱,在懒加载场景下还会出现服务重复实例化的问题。
修复方案
按以下步骤调整即可解决问题:
- 移除
SharedService上的providedIn: 'root'配置,避免服务提前注册到不对的注入器层级:@Injectable() export class SharedService{ constructor( private store: Store, @Inject(API_REQUESTS) private apiRequests: ApiRequestInterface[] ) { debugger; } } - 把
SharedService加入ApiModule.forRoot()返回的提供者列表,保证服务和它依赖的API_REQUESTS令牌注册在同一个注入器,同时给入参加默认空数组避免传空时出现undefined:static forRoot(apiRequests: ApiRequestInterface[] = []): ModuleWithProviders<ApiModule> { return { ngModule: ApiModule, providers: [ SharedService, {provide: API_REQUESTS, useValue: apiRequests} ] }; } - 调整模块导入规则:
- 只在根模块
AppModule中调用ApiModule.forRoot(你的实际API配置数组),所有其他业务模块(包括懒加载模块)如果需要用到ApiModule的能力,直接导入ApiModule本身即可,绝对不要在业务模块调用forRoot() - 删掉所有业务模块
providers数组里的SharedService声明,避免重复生成服务实例
- 只在根模块
- (可选优化)补全ApiModule构造函数里的重复导入检测逻辑,避免后续误用:
constructor(@Optional() @SkipSelf() parentModule: ApiModule ) { if (parentModule) { throw new Error('ApiModule仅可在根模块通过forRoot()导入,业务模块请直接导入ApiModule本身'); } }
调整完成后,服务和依赖的令牌都在根注入器注册,层级匹配,就不会再出现找不到注入器的报错。
内容的提问来源于stack exchange,提问作者Nealv
相关产品推荐
相关产品推荐

