我有 2 个 APP_INITIALIZER 提供程序...第一个发出 HTTP 请求以获取环境信息。
第二个使用环境信息根据 OIDC 授权服务器端点(从环境调用获得)授权用户。
看起来,尽管使环境服务成为授权服务的依赖项,授权服务的 APP_INITIALIZER 工厂函数在环境调用完成之前被调用。
{ provide: APP_INITIALIZER, multi: true, useFactory: EnvironmentFactory, deps: [] }
{ provide: APP_INITIALIZER, multi: true, useFactory: AuthorizationFactory, deps: [EnvironmentProvider] }
提供给 APP_INITIALIZER 的两个工厂都具有签名:
Factory() { return () => Promise; }
结果是授权调用提交到 undefined
而不是正确的 URL。
我考虑过合并工厂 - 但它们位于两个不同的模块中,所以感觉很乱。指导表示赞赏!
最佳答案
我最终将已解析的 EnvironmentProvider 注入(inject)到 AuthorizationFactory 中。
我向 EnvironmentProvider 添加了一个可观察对象,它会在 Authority 值发生变化时发出。
{ provide: APP_INITIALIZER, multi: true,
useFactory: EnvironmentFactory, deps: [EnvironmentProvider] }
{ provide: APP_INITIALIZER, multi: true, useFactory: AuthorizationFactory,
deps: [AuthorizationProvider, EnvironmentProvider] }
export function AuthorizationFactory (auth: AuthorizationProvider, env: EnvironmentService) {
return new Promise((resolve, reject) => env.Authority$()
// don't emit until authority provider has a value
.skipWhile(authority => !authority)
// dispatch the auth command to ngrx/store.
.do(() => store.dispatch({ type: 'AuthorizeIdentity' }))
// switch to observe identity state
.switchMap(() => store.select('Identity'))
// don't emit until there is an identity (async authorization complete).
.skipWhile(identity => !identity)
// finish.
.take(1)
.subscribe(resolve, reject)
});
}
我使用 ReplaySubject(1)
作为 env.Authority$() 的来源。这确保返回的可观察对象始终在 AuthorizationFactory 订阅时发出(例如,如果在 AuthorizationFactory 订阅之前解析了权限)。
遇到此问题的任何人都想知道为什么我不使用 toPromise()...我认为存在一些问题(我已在此处提交以供审核)。 https://github.com/Reactive-Extensions/RxJS/issues/1429
关于Angular 2 APP_INITIALIZER 执行顺序/异步问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42572028/