gpt4 book ai didi

Angular 导入的模块不等待 APP_INITIALIZER

转载 作者:行者123 更新时间:2023-12-04 11:29:57 26 4
gpt4 key购买 nike

我正在尝试使用 auth0/auth0-angular Angular 11 应用程序中的库。
我正在关注 loading config dynamically 上的部分.
它提供了这个示例应用模块代码:

// app.module.ts
// ---------------------------
import { AuthModule, AuthClientConfig } from '@auth0/auth0-angular';

// Provide an initializer function that returns a Promise
function configInitializer(
handler: HttpBackend,
config: AuthClientConfig
) {
return () =>
new HttpClient(handler)
.get('/config')
.toPromise()
.then((loadedConfig: any) => config.set(loadedConfig)); // Set the config that was loaded asynchronously here
}

// Provide APP_INITIALIZER with this function. Note that there is no config passed to AuthModule.forRoot
imports: [
// other imports..

HttpClientModule,
AuthModule.forRoot(), //<- don't pass any config here
],
providers: [
{
provide: APP_INITIALIZER,
useFactory: configInitializer, // <- pass your initializer function here
deps: [HttpBackend, AuthClientConfig],
multi: true,
},
],
简而言之,它使用 APP_INITIALIZER提供程序通过 Promise 动态加载配置,这应该在 Auth0 库的 AuthModule 之前完成被实例化,以便它具有从 API 和 AuthClientConfig.set(...) 加载的适当 Auth0 配置值已提前使用这些值调用。
Angular APP_INITIALIZER documentation说:

If any of these functions returns a Promise, initialization does not complete until the Promise is resolved.


所以,他们的例子从表面上看是有道理的。
但是,当我尝试在自己的应用程序中实际实现此解决方案时,出现以下错误:
Error: Configuration must be specified either through AuthModule.forRoot or through AuthClientConfig.set
这表明 AuthModule在加载和设置配置之前已实例化。
在我看来,Angular 实际上并不是在等待 Promise在它开始实例化导入的模块之前解决。
我认为这个 StackBlitz demo在没有任何 Auth0 依赖项的简化示例中演示了问题。
在这个例子中,我希望 TestModule直到 Promise 之后才被实例化已解决,所以我应该看到以下控制台输出:
Inside factory method
Inside promise
Inside timeout
TestModule constructor
但我实际看到的是:
TestModule constructor
Inside factory method
Inside promise
Inside timeout
有人可以帮我理解 APP_INITIALIZER的确切性质吗? ,即它什么时候被调用,Angular 什么时候等待 Promise要解决,Angular 什么时候开始实例化其他模块,为什么我的 Auth0 设置可能无法正确加载,等等?

最佳答案

TL;博士 - 我最终通过在 main.ts 中加载配置来解决这个问题在引导应用程序之前,然后通过自定义注入(inject) token 使配置可用,然后我的应用程序配置服务不需要等待它通过 HTTP 加载,因为它已经可用。
详情
我的 AppConfig 的片段界面:

export interface AppConfig {
auth: {
auth0_audience: string,
auth0_domain: string,
auth0_client_id: string,
};
}
定制 InjectionToken在我的常量文件中:
 const APP_CONFIG: InjectionToken<AppConfig>
= new InjectionToken<AppConfig>('Application Configuration');
main.ts :
fetch('/config.json')
.then(response => response.json())
.then((config: AppConfig) => {
if (environment.production) {
enableProdMode();
}

platformBrowserDynamic([
{ provide: APP_CONFIG, useValue: config },
])
.bootstrapModule(AppModule)
.catch(err => console.error(err));
});
然后在我的主 AppModule我导入了 Auth0 AuthModule.forRoot()没有配置并调用我自己的 AppConfigService配置 AuthModule .
我还需要 APP_INITIALIZER依赖 AppConfigService并返回 Promise这以某种方式让 Angular 等到 AppConfigService构造函数已被调用,但它不会做任何事情(并且仍然不会延迟 AuthModule 被初始化),所以我只是立即解决它。 AppModule :
@NgModule({
declarations: [
...
],
imports: [
AuthModule.forRoot(),
...
],
providers: [
AppConfigService,
{
provide: APP_INITIALIZER,
useFactory: () => () => {
return new Promise(resolve => {
resolve();
});
},
deps: [ AppConfigService ],
multi: true,
},
{
provide: HTTP_INTERCEPTORS,
useClass: AuthHttpInterceptor,
multi: true,
},
],
bootstrap: [ AppComponent ],
})
export class AppModule { }
最后, AppConfigService :
@Injectable()
export class AppConfigService {

constructor(
@Inject(APP_CONFIG) private readonly appConfig: AppConfig,
private authClientConfig: AuthClientConfig,
) {
this.authClientConfig.set({
clientId: this.appConfig.auth.auth0_client_id,
domain: this.appConfig.auth.auth0_domain,
audience: this.appConfig.auth.auth0_audience,
httpInterceptor: {
allowedList: [
...
],
},
});
}
}
这一切似乎都很好,尽管我仍然不明白 APP_INITIALIZER 的确切性质我不太高兴调用 Auth0 客户端配置的 set构造函数中的方法,而不是文档建议的异步“加载”方法。

关于Angular 导入的模块不等待 APP_INITIALIZER,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66859984/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com