Angular:在應用初始化時運行代碼

想象一下,您的應用須要一些動態配置信息,這些信息在應用啓動以前須要動態獲取,並在應用運行中使用。api

顯然不能直接寫道靜態配置文件中,可是從客戶端發出的請求又是一個異步請求,如何協調這個問題呢?數組

這裏,我想向您演示,如何在 Angular 應用初始化期間,使用 APP_INITIALIZER 注入器來獲取應用的動態配置信息。promise

什麼是 APP_INITIALIZER 注入器

APP_INITIALIZER 是容許您在 Angular 初始化七千處理您本身任務的機制。它既能夠用於 AppModule,核心模塊,也能夠用於您本身的應用加載模塊中。典型的場景是應用加載以前作的事情,好比從服務處加載用於設置應用的配置信息。在示例中,咱們使用它從服務器的 XML 配置文件中加載應用的設置信息。服務器

建立 AppLoad 模塊

儘管不是必要,經過建立 App Load module 仍是對應用加載有助於隔離。併發

import { NgModule, APP_INITIALIZER } from '@angular/core';
import { HttpClientModule } from "@angular/common/http";
 
import { AppLoadService } from './app-load.service';
 
export function init_app(appLoadService: AppLoadService) {
    return () => appLoadService.initializeApp();
}
 
export function get_settings(appLoadService: AppLoadService) {
    return () => appLoadService.getSettings();
}
 
@NgModule({
  imports: [HttpClientModule],
  providers: [
    AppLoadService,
    { provide: APP_INITIALIZER, useFactory: init_app, deps: [AppLoadService], multi: true },
    { provide: APP_INITIALIZER, useFactory: get_settings, deps: [AppLoadService], multi: true }
  ]
})
export class AppLoadModule { }

注意一下幾點:app

  • APP_INITIALIZER 導入自 @angular/core
  • 這裏有多個 APP_INITIALIZER,它們在應用初始化過程當中併發執行,直到它們所有完成。
    •   使用 nulti: true 用於多個注入器,若是隻有一個,使用 multi: false。
  • 工廠函數 init_app 和 get_settings 應當返回一個返回 Promise 的函數。
  • 該模塊必須添加到 AppModule 的導入數組中。

建立 App Load Service

AppLoadService 應當隔離您在應用初始化期間的做爲。固然這不是必須的,您可使用任何須要的服務。異步

這裏實現了兩個方法咱們在前面代碼中使用的方法。在咱們的 AppLoadModule 中做爲依賴注入到提供器數組中。ide

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import 'rxjs/add/operator/toPromise';
 
import { APP_SETTINGS } from '../settings';
 
@Injectable()
export class AppLoadService {
 
  constructor(private httpClient: HttpClient) { }
 
  initializeApp(): Promise<any> {
    return new Promise((resolve, reject) => {
          console.log(`initializeApp:: inside promise`);
 
          setTimeout(() => {
            console.log(`initializeApp:: inside setTimeout`);
            // doing something
 
            resolve();
          }, 3000);
        });
  }
 
  getSettings(): Promise<any> {
    console.log(`getSettings:: before http.get call`);
    
    const promise = this.httpClient.get('http://private-1ad25-initializeng.apiary-mock.com/settings')
      .toPromise()
      .then(settings => {
        console.log(`Settings from API: `, settings);
 
        APP_SETTINGS.connectionString = settings[0].value;
        APP_SETTINGS.defaultImageUrl = settings[1].value;
 
        console.log(`APP_SETTINGS: `, APP_SETTINGS);
 
        return settings;
      });
 
    return promise;
  }
}

注意如下幾點:函數

  • initializeApp 用於等待 3 秒,並輸出日誌來顯示兩個方法是並行執行的。
  • getSettings 調用一個模擬的我使用 APIARY 建立的 API 來或者設置。
    •   這裏使用這些設置來設置 APP_SETTINGS 對象的
  •   它們都返回 Promise 

運行應用

運行應用,能夠在 Console 中查看以下輸出this

注意:

  • 您能夠看到兩個方法都被調用了。
  • 設置首先返回
  •  initializeApp 最後完成,而後應用啓動。

如何從 settings 中獲取 API 的地址?

有些人想:「若是沒有 settings 來知道 URL, 我如何調用 API 呢?」,這是一個問題,您能夠經過一個相對 URL 來經過 HttpClient ,並假設 API 在您的 Web 站點上。

 

參考資料

https://www.intertech.com/Blog/angular-4-tutorial-run-code-during-app-initialization/

相關文章
相關標籤/搜索