8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Angular】アプリの初期画面表示より前に処理を行いたい

Last updated at Posted at 2019-12-27

はじめに

以前書いたこの記事では、データ取得からスタイル反映までにラグがあったためチラついたように見えるのが問題だった。
具体的にはこんな感じ。ネットワークが遅いとより顕著だ。
custom-color-fail-1.gif

そこで今回はそもそもアプリの初期画面表示よりも前に処理を行う方法を共有する。

初期表示前に処理を行うにはAPP_INITIALIZEを使用する

公式 → APP_INITIALIZER
(全然書いてない…。)

初期表示前に行う関数でServiceクラスが使われている場合、そのServiceクラスがproviders:[]に追加されているmodule.tsに追加する。※あちこちに散らばるのを防ぐ狙い
useFactoryには初期表示前に行う関数を指定。multitrueに設定すると複数のproviderを使用できるようだ。(が正直ここはわかってない)
参考サイト

With multi: true providing multiple providers with the same key (APP_INITIALIZER) won't override the previous one (behavior with multi: false), but DI will collect them in an array itself

depsuseFactoryで指定されている関数内で使用されるServiceクラスを指定する。

core.module.ts
import { APP_INITIALIZER, NgModule} from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { ThemeColorService } from './services/theme-color.service';
import { themeColorInitializer } from './app-initializer/theme-color-initializer';

@NgModule({
    declarations: [],
    imports: [CommonModule, HttpClientModule],
    providers: [
        // これを追加↓
        {
            provide: APP_INITIALIZER,
            useFactory: themeColorInitializer,
            multi: true,
            deps: [ThemeColorService],
        },
        ThemeColorService,
    ],
})
export class CoreModule {
    constructor() { }
}

useFactoryに渡される関数を実装

今回の例で言うと「テーマカラーを取得し、セットする」処理を実装。
既存のServiceクラスを使いたい場合は引数にそのまま渡す。privateを付けないことに注意。

theme-color-initializer.ts
import { ThemeColorService } from '../services/theme-color.service';

/**
 * アプリのテーマカラーの取得をAngularアプリがレンダリングする前に行う。
 * @param appThemeColor
 */
export function themeColorInitializer(appThemeColor: ThemeColorService) {
    return () => appThemeColor.initialize();
}

ちなみにこのファクトリー関数は、「Promiseを返却する関数」を返却する関数を実装する必要がある。 このPromiseが解決されて初めてAngularアプリのBootstrapプロセスが続行されるような仕組み。
さらにここではHttpClientも使用でき、その場合はmodule.tsimportsHttpClientModuledepsHttpClientを含める必要がある。(今回の場合だとServiceクラスでラップしているのでdepsへの追加はServiceクラスだけで大丈夫。)

The factory function is expected to return a Promise and only after the promise has resolved will the application bootstrap process continue
...
larly, you could use an HTTP service (from HttpClient) to request data from an API and only after the request is complete that the application bootstrap process would continue. However, to use Angular's HttpClient in the initApp factory function, include HttpClientModule in the imports section and also specify HttpClient as a dependency ( deps) to the APP_INITIALIZER provider

ついでにこのServiceクラスの中身はこんな感じ。

ThemeColorService
import { Injectable } from '@angular/core';
import { catchError, tap } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';

interface ThemeColor {
    themeColor: string;
}

@Injectable({
    providedIn: 'root',
})
export class ThemeColorService {
    constructor(private http: HttpClient) {}

    /**
     * テーマカラーの初期化を行う
     */
    public async initialize() {
        const id = 1; // ここはアプリ毎に可変だが一旦仮置き
        return this.http
            .get<ThemeColor>(`https://example.com/app/${id}/theme-color`)
            .pipe(
                tap(({themeColor}) => ThemeColorService.setThemeColor(themeColor)),
                catchError(() => ThemeColorService.setDefaultColor())
            )
            .toPromise();
    }

    /**
     * テーマカラーを反映する
     */
    private static setThemeColor(themeColor: string) {
        document.documentElement.style.setProperty('--main-color', themeColor);
    }

    /**
     * デフォルトのテーマカラーをセットする。
     */
    private static async setDefaultColor() {
        document.documentElement.style.setProperty('--main-color', 'red');
    }
}

取得に成功したらテーマカラーをセット、失敗したらデフォルトカラーをセットし最後にtoPromise()でPromiseを返却する。

これでひとまず準備は完了だ。

確認してみる

この通り表示されるときには既に色が反映されるようになった。
custom-color-success.gif

参考

8
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?