APP_INITIALIZER在出厂前未触发

use*_*854 5 dependency-injection typescript angular

APP_INITIALIZER用来加载环境特定的变量。我需要在我的中使用这些变量authConfigFactory,但是工厂会APP_INITIALIZER在应用程序配置内部完成之前保持加载状态。

我正在使用这个库:https : //github.com/manfredsteyer/angular-oauth2-oidc

我想使用APP_CONFIG.authConfig.allowedUrls我的auth config工厂内部的值。我如何确保它在认证工厂之前先设置配置。

我在工厂收到此错误: Cannot read property 'authConfig' of undefined

app.module.ts

providers: [
    AppConfigService,
    {
      provide: APP_INITIALIZER,
      useFactory: (config: AppConfigService) => () => config.load(),
      multi: true,
      deps: [AppConfigService]
    },
    {
      provide: OAuthModuleConfig,
      useFactory: authConfigFactory
    }
]
Run Code Online (Sandbox Code Playgroud)

app.config.ts

export let APP_CONFIG: AppConfig;

@Injectable()
export class AppConfigService {
  constructor(
    private injector: Injector
  ) {}

  config = null;

  public load() {
    const http = this.injector.get(HttpClient);

    return http
      .get('../assets/config/config.json')
      .pipe(
        tap(returnedConfig => {
          const t = new AppConfig();
          APP_CONFIG = Object.assign(t, returnedConfig);
        })
      )
      .toPromise();
  }

}
Run Code Online (Sandbox Code Playgroud)

auth-config-factor

export function authConfigFactory(): OAuthModuleConfig {
  return {
    resourceServer: {
      allowedUrls: APP_CONFIG.authConfig.allowedUrls,
      sendAccessToken: true
    }
  };
}
Run Code Online (Sandbox Code Playgroud)

Fat*_*med 3

我以前遇到过这个问题,尝试了很多可能性但没有成功,唯一的解决方案是我使用 ngrx/store

在 app.config.ts 中,您可以调度一个操作来将配置保存在商店中,然后您可以通过执行以下操作在其他服务中获取它: store.select() 订阅它并进行控制

应用程序模块.ts

providers: [
 AuthService, // oidc-client.ts where i need the config from json
 DataService,
 ConfigService,
 {
  provide: APP_INITIALIZER,
  useFactory: loadConfig,
  deps: [ConfigService],
  multi: true,
 },
Run Code Online (Sandbox Code Playgroud)

配置服务.ts

  import { HttpClient } from '@angular/common/http';
  import { Injectable } from '@angular/core';
  import { Store } from '@ngrx/store';
  import { IAppStore } from '../models/store.model';
  import * as ConfigActions from '../store/actions/config.actions';

  @Injectable()
   export class ConfigService {
   public config: any = {};

   constructor(private http: HttpClient, private store: Store<IAppStore>) {}

   getConfig(key: string): string {
     return this.config[key] || '';
    }
  public loadConfig() {
     return new Promise((resolve, reject) => {
      this.http.get('app-config.json').subscribe(
      (response) => {
        this.config = response;
        this.store.dispatch(new ConfigActions.AddConfig(response)); // dispatch action to update the store
        resolve(true);
      }
    );
  });
  }}
Run Code Online (Sandbox Code Playgroud)

认证服务

  import { Log, User, UserManager, WebStorageStateStore } from 'oidc-client';
  ...
  @Injectable()
  export class AuthService {
  private _userManager: UserManager;
  public _user: User;
  constructor(
    private store: Store<IAppStore>
    private httpClient: HttpClient,
    private route: Router,
    private configs: ConfigService
  ) {
this.store.select('appConfig').subscribe((configdata) => {
  Log.logger = console;
  const config = {
  authority: configdata.stsAuthority,
  client_id: configdata.clientId,
  redirect_uri: `${configdata.clientRoot}/#/auth-callback#`,
  scope: 'openid profile fusionApi.full_access',
  response_type: 'id_token token',
  post_logout_redirect_uri: `${configdata.clientRoot}?postLogout=true`, // delet all stored tokens after logout
  userStore: new WebStorageStateStore({ store: window.localStorage }),
  automaticSilentRenew: true,
  silent_redirect_uri: `${configdata.clientRoot}/assets/html/silent-refresh-redirect.html`,
};
  this._userManager = new UserManager(config);
  this._userManager.getUser().then((user) => {
  if (user && !user.expired) {
    this._user = user;
  }
});
 ...
}

login(): Promise<any> {
 return this._userManager.signinRedirect();
}
...
Run Code Online (Sandbox Code Playgroud)