簡體   English   中英

APP_INITIALIZER 不等待(Angular 13)

[英]APP_INITIALIZER not awaiting (Angular 13)

我正在從 okta/okta-angular 3.x 更新到 5.x。 它似乎引入了一個奇怪的錯誤。

當應用程序第一次啟動時,我們一直在使用 APP_INITIALIZER 執行appInitializerFactory(configService: ConfigService) ,它會調用 http 來加載配置數據。

調用如下所示:

  public async loadConfig(): Promise<any> {
    return this.httpClient.get('assets/config.json').pipe(settings => settings)
      .toPromise()
      .then(settings => {
        this.config = settings as IAppConfig;
      })
      .catch(exception => {
        console.log("Exception encountered while retreiving configuration");
      });
  }

在更新到 okta 5.x 之前,APP_INITIALIZER 一直在等待 promise。 現在,在 APP_INITILIZER 中的 promise 完成之前,似乎正在解決其他提供程序。

產生的問題發生在oktaInitializerFactory的下游,它運行以下代碼:

public oktaConfig() {
    return Object.assign({
      onAuthRequired: (oktaAuth: OktaAuth, injector: Injector) => {
        const router = injector.get(Router);
        router.navigate(['/login']);
      }
    }, this.config.oktaConfig);
  }

在最后一行, this.config.oktaConfigundefined的形式返回,因為 APP_INITIALIZER 尚未完成等待。

這是完整的 app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { Routes, RouterModule, Router } from '@angular/router';
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { MaterialModule } from './modules/material/material.module';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { TablesComponent } from './components/tables/tables.component';
import { PageNotFoundComponent } from './components/page-not-found/page-not-found.component';
import { DashboardComponent } from './components/dashboard/dashboard.component';
import { ToolbarComponent } from './components/toolbar/toolbar.component';
import { LoginComponent } from './components/login/login.component';
import { FormsModule } from '@angular/forms';
import { RunLogComponent } from './components/run-log/run-log.component';
import { RunDataComponent } from './components/run-data/run-data.component';
import { ActionComponent } from './components/action/action.component';
import { ErrorsComponent } from './components/errors/errors.component';
import { OktaAuth } from '@okta/okta-auth-js';
import { OKTA_CONFIG, OktaAuthGuard, OktaAuthModule, OktaCallbackComponent } from '@okta/okta-angular';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { TabulatorUserTableComponent } from './components/tabulator-user-table/tabulator-user-table.component';
import { TabulatorTableComponent } from './components/tabulator-table/tabulator-table.component';
import { DataLakeComponent } from './components/data-lake/data-lake.component';
import { IntegrationHistoryComponent } from './components/integration-history/integration-history.component';
import { IntegrationStatusComponent } from './components/integration-status/integration-status.component';
import { MatSpinnerButtonComponent } from './components/mat-spinner-button/mat-spinner-button.component';
import { ConfigService } from './services/config.service';
import { DataStudioComponent } from './components/data-studio/data-studio.component';
import { IntegrationDashboardComponent } from './components/integration-dashboard/integration-dashboard.component';
import { IntegrationSelectorToolbarComponent } from './integration-selector-toolbar/integration-selector-toolbar.component';
import { PrimaryButtonsComponent } from './components/primary-buttons/primary-buttons.component';
import { UserCardComponent } from './components/user-card/user-card.component';
import { HttpOktaInterceptorService } from './services/http-okta-interceptor.service';
import { DebugInfoComponent } from './components/debug-info/debug-info.component';
import { ModalModule } from './modal';
import { DragNDrop } from './components/dropbox/drag-n-drop';
import { ProgressComponent } from './components/dropbox/progress/progress.component';


const appRoutes: Routes = [
  {
    path: '',
    component: DashboardComponent,
    canActivate: [OktaAuthGuard]
  },
  {
    path: 'login/callback',
    component: OktaCallbackComponent
  },
  {
    path: 'login',
    component: LoginComponent
  }
];

@NgModule({
  declarations: [
    AppComponent,
    TablesComponent,
    PageNotFoundComponent,
    DashboardComponent,
    ToolbarComponent,
    LoginComponent,
    RunLogComponent,
    RunDataComponent,
    ActionComponent,
    ErrorsComponent,
    TabulatorUserTableComponent,
    TabulatorTableComponent,
    DataLakeComponent,
    IntegrationHistoryComponent,
    IntegrationStatusComponent,
    MatSpinnerButtonComponent,
    DataStudioComponent,
    IntegrationDashboardComponent,
    IntegrationSelectorToolbarComponent,
    PrimaryButtonsComponent,
    UserCardComponent,
    DebugInfoComponent,
    ProgressComponent,
    DragNDrop
  ],
  imports: [
    BrowserModule,
    OktaAuthModule,
    RouterModule.forRoot(appRoutes, { relativeLinkResolution: 'legacy' }),
    BrowserAnimationsModule,
    MaterialModule,
    FormsModule,
    HttpClientModule,
    ModalModule
  ],
  providers: [
    { 
      provide: APP_INITIALIZER, 
      useFactory: appInitializerFactory, 
      deps:[ConfigService], 
      multi: true
    },
    { 
      provide: OKTA_CONFIG, 
      useFactory: oktaInitializerFactory, 
      deps:[ConfigService],
    },
    {
      provide: HTTP_INTERCEPTORS,
      useClass: HttpOktaInterceptorService,
      multi: true,
      deps: [OktaAuth]
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

export function appInitializerFactory(configService: ConfigService) {
  return () => configService.loadConfig();
}

export function oktaInitializerFactory(configService: ConfigService) {
  return configService.oktaConfig();
}

我的 APP_INITIALIZER 在其他代碼執行之前沒有完成是否有特殊原因? 當我降級回 okta 3.x 時,這個問題就消失了。

事實證明,從Okta 3升級到4+5+確實引入了一個變化,這使得在APP_INITIALIZER中加載身份驗證服務器配置成為一個不可行的選項。

簡而言之,okta-angular 將在APP_INITIALIZER完成之前嘗試連接到身份驗證服務器。 解決方法是將配置數據加載到 main.ts 中的注入器中,該注入器在main.ts之前APP_INITIALIZER 這在技術上違背了angular.io中的文檔,但Okta 支持已經驗證了這種行為[ 來源]

另一個用戶對 Auth0 做了類似的實現,遇到了同樣的問題,鏈接在這里: stackoverflow.com/a/66957293/3202440

我不知道它在以前的版本中應該如何工作。 你有依賴於ConfigServiceappInitializerFactory ConfigService依賴於HttpClient HttpClient => HTTP_INTERCEPTORS即在HttpOktaInterceptorService上。 HttpOktaInterceptorService => OktaAuth這很可能依賴於OKTA_CONFIG

這意味着要構造一個HttpClient (它隱式地要求初始化器),您需要已經構造了OKTA_CONFIG 聽起來很合乎邏輯的是,這個配置初始化程序比APP_INITIALIZER更早地被調用。

這種依賴很可能是在重構期間引入的,而不僅僅是更新。

在您的位置,我會嘗試消除對ConfigServiceHttpClient的依賴,並使用本機 api 發出此請求

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM