如何在Angular 5组件中注入AngularJS服务?ngUpgrade迁移遇报错
你遇到的Trying to get the AngularJS injector before it being set错误,核心原因是Angular组件的初始化早于AngularJS应用的引导完成。让我一步步帮你理清问题和解决方案:
为什么当前方法无效?
你现在的引导流程是先启动Angular的AppModule,再通过UpgradeModule启动AngularJS。但Angular的根组件AppComponent会在bootstrapModule完成后立刻初始化,这时候AngularJS的注入器还没被设置,导致依赖AngularJS服务的LoginPageComponent在构造函数里获取$injector时失败。
修复方案:调整引导顺序
我们需要确保AngularJS先完成引导,再初始化Angular组件。具体修改如下:
1. 修改app.module.ts
移除bootstrap数组,改用ngDoBootstrap手动控制引导顺序,同时把根组件加入entryComponents:
import { NgModule, ApplicationRef } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { UpgradeModule } from '@angular/upgrade/static'; import { AppComponent } from './app.component'; import { LoginPageComponent } from './login.component'; import { authenticationServiceProvider } from './ajs-upgraded-providers'; @NgModule({ declarations: [ AppComponent, LoginPageComponent ], imports: [ BrowserModule, UpgradeModule, ], providers: [ authenticationServiceProvider, ], entryComponents: [AppComponent], // 手动引导需要加入这里 // 移除自动引导的bootstrap数组 }) export class AppModule { constructor(private upgrade: UpgradeModule) {} ngDoBootstrap(appRef: ApplicationRef) { // 第一步:先引导AngularJS应用,确保注入器就绪 this.upgrade.bootstrap(document.documentElement, ['myAngularJSApp']); // 第二步:再引导Angular根组件 appRef.bootstrap(AppComponent); } }
2. 简化main.ts
现在引导逻辑都在AppModule里了,main.ts只需要启动Angular模块即可:
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; import { environment } from './environments/environment'; // 导入AngularJS模块 import '../ajs/app'; platformBrowserDynamic() .bootstrapModule(AppModule) .catch(err => console.error(err));
关于forwardRef的疑问
你提到的forwardRef其实和当前问题无关,它主要用于解决循环依赖场景(比如组件A依赖服务B,服务B又依赖组件A)。你的问题是注入器初始化顺序问题,所以不需要用到它。
更简化的服务升级方式
Angular的UpgradeModule提供了upgradeInjectable方法,可以帮你省去手动写factory的麻烦,直接把AngularJS服务升级为Angular服务:
修改ajs-upgraded-providers.ts:
import { upgradeInjectable } from '@angular/upgrade/static'; import { AuthenticationService } from '../ajs/services/authentication.service'; // 直接用upgradeInjectable关联AngularJS服务和Angular类 export const authenticationServiceProvider = upgradeInjectable({ provide: AuthenticationService, useExisting: 'authentication' // 这里要和AngularJS中注册的服务名称完全一致 });
这样写和你之前的factory逻辑是等价的,但代码更简洁。
最后检查点
- 确认AngularJS中注册的服务名称确实是
'authentication'(和你在代码中$injector.get('authentication')的名称一致) - 确保AngularJS模块
'myAngularJSApp'已经正确导入并注册了authentication服务
内容的提问来源于stack exchange,提问作者Stephan Muller

