如何解决模块中的 Angular APP_INITIALIZER 无法正常工作
我有 auth 模块,它在应用程序初始化之前导入和设置 msal 配置。我正在使用 APP_INITIALIZER 来阻止应用程序的初始化并获取 MSAL-ANGULAR 的配置。 问题仅与 Firefox 有关。该应用程序在 Chrome、Egde、Safari 上运行良好,但在 Firefox 上运行不正常。在与 Firefox 不同的所有其他浏览器上,APP_INITIALIZER 会阻止启动,直到加载 config.json。 我注意到的是 MSALInstanceFactory 在 initializerFactory 函数之前被调用。
我在 auth.module 中使用的代码
export function initializerFactory(env: ConfigService,configUrl: string): any {
// APP_INITIALIZER,angular doesnt starts application untill it completes loading config.json
const promise = env.init(configUrl).then(val => {});
return () => promise;
}
export function loggerCallback(logLevel: LogLevel,message: string): void {
console.log(message);
}
export function MSALInstanceFactory(configService: ConfigService,constant: SecurityConstants): IPublicclientApplication {
return new PublicclientApplication({
auth: {
clientId: configService.getSettings('clientId'),redirectUri: configService.getSettings('redirectUri'),authority: configService.getSettings('authority'),},cache: {
cacheLocation: browserCacheLocation.LocalStorage,storeAuthStateInCookie: isIE,system: {
loggerOptions: {
loggerCallback,logLevel: LogLevel.Info,piiLoggingEnabled: false,});
}
export function MSALInterceptorConfigFactory(configService: ConfigService,constant: SecurityConstants): MsalInterceptorConfiguration {
const protectedResourceMap = new Map<string,Array<string>>();
protectedResourceMap.set('/*/',[configService.getSettings('scope')]);
return {
interactionType: InteractionType.Redirect,protectedResourceMap,};
}
export function MSALGuardConfigFactory(configService: ConfigService,constant: SecurityConstants): MsalGuardConfiguration {
return {
interactionType: InteractionType.Redirect,authRequest: {
scopes: [configService.getSettings('scope')],};
}
@NgModule({
imports: [MsalModule]
})
export class AuthModule {
static forRoot(configFile: string) {
return {
ngModule: AuthModule,providers: [
ConfigService,MsalService,{ provide: AUTH_CONfig_URL_TOKEN,useValue: configFile },{
provide: APP_INITIALIZER,useFactory: initializerFactory,deps: [ConfigService,AUTH_CONfig_URL_TOKEN,SecurityConstants],multi: true,{
provide: HTTP_INTERCEPTORS,useClass: MsalInterceptor,{
provide: MSAL_INSTANCE,useFactory: MSALInstanceFactory,// this is initiated before APP_INITIALIZER
deps: [ConfigService,{
provide: MSAL_GUARD_CONfig,useFactory: MSALGuardConfigFactory,{
provide: MSAL_INTERCEPTOR_CONfig,useFactory: MSALInterceptorConfigFactory,MsalGuard,MsalbroadcastService,],};
}
}
@Injectable({
providedIn: 'root',})
export class ConfigService {
config: any;
private http: HttpClient;
constructor(private readonly httpHandler: HttpBackend) {
this.http = new HttpClient(httpHandler);
}
init(endpoint: string): Promise<boolean> {
let promise = new Promise<boolean>((resolve,reject) => {
this.http
.get<ConfigResponse>(endpoint)
.pipe(map((res) => res))
.subscribe(
(value) => {
this.config = value;
},(error) => {
reject(false);
},() => {
resolve(true);
}
);
});
return promise;
}
getSettings(key?: string | Array<string>): any {
if (!key || (Array.isArray(key) && !key[0])) {
return this.config;
}
if (!Array.isArray(key)) {
key = key.split('.');
}
let result = key.reduce((acc: any,current: string) => acc && acc[current],this.config);
return result;
}
}
app.module 中的代码
@NgModule({
declarations: [AppComponent],imports: [
AuthModule.forRoot('assets/config.json'),CommonModule,browserModule,browserAnimationsModule,HttpClientModule,RouterModule
],bootstrap: [AppComponent,MsalRedirectComponent],})
export class AppModule {}
解决方法
我发现 APP_INITIALIZER 并不能保证您的配置服务首先完成。此问题也在此处报告:https://github.com/angular/angular/issues/23279 遗憾的是仍未解决。 最初 MSAL_Instance 在此之前加载,为了解决该问题,我更改了 main.ts 引导模块。
// main.ts
function bootstrapFailed(val) {
document.getElementById('bootstrap-fail').style.display = 'block';
console.error('bootstrap-fail',val);
}
fetch('config.json')
.then(response => response.json())
.then(config => {
if (!config || !config['isConfig']) {
bootstrapFailed(config);
return;
}
// Store the response somewhere that your ConfigService can read it.
window['tempConfigStorage'] = config;
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch(bootstrapFailed);
})
.catch(bootstrapFailed);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。