jaz*_*azz 7 typescript angular
我正在使用 APP_INITIALIZER 从 json 获取配置并且它工作正常。早些时候我有一个身份验证保护作为应用程序的一部分,它曾经很好用。
然后我们将授权逻辑拆分到一个库中,如果我们调用 forRoot() 或者如果我们为 config 提供静态值但允许动态配置,我使用库中的 InjectionToken 来提供配置而不调用 forRoot,它可以正常工作。
app.module.ts的代码是这样的:
let authConfig: any;
export function authConfigFactory() {
return authConfig;
}
export function appInitializerFn(appConfigService: AppConfigService) {
return () => {
return appConfigService.loadAppConfig().then(() => {
authConfig = {
clientId: appConfigService.getConfig().CLIENT_ID,
tokenEndpoint: appConfigService.getConfig().TOKEN_URL,
redirectURL: "http://localhost",
};
});
};
};
@NgModule({
.....
imports: [
..
AuthLib
],
providers: [
AppConfigService,
{
provide: APP_INITIALIZER,
useFactory: appInitializerFn,
multi: true,
deps: [AppConfigService]
},
AuthLibService,
{
provide: 'authConfig',
useFactory: authConfigFactory,
deps: []
},
.....
]
bootstrap: [AppComponent]
})
export class AppModule { }
Run Code Online (Sandbox Code Playgroud)
现在authConfigFactory在appInitializerFn之前被调用,导致未定义,如果我将异步添加到authConfigFactory以防止返回语句直到其定义,则空值被提供给 AuthGuard 导致令牌 URL 无效。
如果我在调用 promise 之前在appInitializerFn 中手动提供值,则值会被转换并且一切正常。但在那个阶段,动态值不存在。
app-config.service.ts 的代码:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { environment } from 'src/environments/environment';
import { AppConfig } from '../_models/app-config';
import { LoggingService } from './logging.service';
@Injectable()
export class AppConfigService {
static appConfig : AppConfig;
private dataLoc: string;
constructor(private http: HttpClient,
private logger: LoggingService) { }
loadAppConfig() {
if(environment.production){
this.dataLoc = '/assets/data/appConfig.json';
}
else{
this.dataLoc = '/assets/data/appConfig-dev.json';
}
return new Promise<void>((resolve, reject) => {
this.http.get(this.dataLoc).toPromise().then((response: AppConfig) => {
AppConfigService.appConfig = <AppConfig>response;
resolve();
}).catch((response: any) => {
reject(`Could not load file '${this.dataLoc}':
${JSON.stringify(response)}`);
});
});
}
getConfig() {
return AppConfigService.appConfig;
}
}
Run Code Online (Sandbox Code Playgroud)
库或代码中缺少什么来使这项工作?
我对 Angular 制度有点陌生,即使我犯了一些愚蠢的错误,也请告诉我。
于是找到原因和解决办法。为任何人发布它绊倒这个问题。
由于 APP_INITIALIZER 被正确调用。我错过的事情是我正在使用“HttpClient”来获取配置,该配置反过来调用在 ROOT 中定义的任何 HTTP_INTERCEPTORS 并最终导致身份验证服务的初始化,这反过来需要身份验证配置作为构造函数中的令牌注入。
因此,即使在获取值之前,令牌也会被注入,导致它未定义/为空。
解决方案虽然很简单,但我们可以使用
在我的情况下,第 3 点是不可能的,因为我想严格控制所有通信,而第 2 点有点笨拙。我们采用了方法 1。共享修改后的代码以供参考。
import { Injectable } from '@angular/core';
import { HttpClient, HttpBackend } from '@angular/common/http';
import { environment } from 'src/environments/environment';
import { AppConfig } from '../_models/app-config';
import { LoggingService } from './logging.service';
@Injectable()
export class AppConfigService {
static appConfig : AppConfig;
private dataLoc: string;
constructor(private handler: HttpBackend,
private logger: LoggingService) { }
loadAppConfig() {
if(environment.production){
this.dataLoc = '/assets/data/appConfig.json';
}
else{
this.dataLoc = '/assets/data/appConfig-dev.json';
}
return new HttpClient(this.handler).get(this.dataLoc)
.toPromise()
.then((data:AppConfig) => {
this.logger.info(data);
AppConfigService.appConfig = data;
});
}
getConfig() {
return AppConfigService.appConfig;
}
}
Run Code Online (Sandbox Code Playgroud)
感谢@ysf,您的最小示例让我知道,如果它一般正常工作,那么在初始化期间还有其他东西正在调用 authconfig 。
归档时间: |
|
查看次数: |
2695 次 |
最近记录: |