サーバーへの複数の呼び出しがある現実のアプリケーションを開発すると、バグだらけになってしまうことがあります。 ここにいらっしゃるということは、API 呼び出しの遅延に苦労されたことがあるということでしょう。 これらの遅延は、ネガティブな UX を引き起こす可能性があります。 今日は、Angular 8のRoute Resolversについて理解しましょう。 ユーザーエクスペリエンスを向上させるためにできることは、プログレスインジケーターを表示するなど、いくつか種類があります。
What Is an Angular Route Resolver?
A Resolver is a class that implements the Resolve interface of Angular Router.Resolverは、Angular RouterのResolveインターフェイスを実装するクラスです。 実際、リゾルバはルート モジュールになければならないサービスです。 基本的に、リゾルバはミドルウェアのように動作し、コンポーネントがロードされる前に実行することができます。
You may also like: Angularのリゾルバ。
Why Use Route Resolvers in Angular?
Angular でリゾルバを使用する方法を説明するために、*ngIf="some condition"
を使用しているときのシナリオを考えてみましょう。 たとえば、順番なしリストで取得されたこの配列のアイテムをコンポーネントに表示したいとします。
<ul><li *ngFor="let item of items">{{item.description}}</li></ul>
この状況では、データがコンポーネントの準備ができた後に表示されるため、問題に直面する可能性があります。 配列内のアイテムはまだ実際には存在しません。 ここで、ルート リゾルバが役に立ちます。 AngularのRoute Resolverクラスは、コンポーネントが準備される前にデータを取得します。 条件文はリゾルバでスムーズに動作します。
Resolve Interface
ルートリゾルバの実装を始める前に、まず Resolve インターフェースがどのように見えるかを確認しましょう。 このインターフェイスは resolve
関数を提供し、必要であれば 2 つのパラメータを取得します。 最初のものはルートで、タイプはActivatedRouteSnapshot
、2番目はステートで、タイプはRouterStateSnapshot
です。 ここで、コンポーネントがロードされる前に必要なデータを取得する API 呼び出しを行うことができます。
Route パラメータを介して、API 呼び出しで使用される可能性のあるルート パラメータを取得することができます。 resolve
メソッドは Observable
、プロミス、または単なるカスタム型を返すことができます。
注意: このメソッドを通じて、解決済みのデータのみが返されることを言及することが重要です。
これは、リゾルバを初めて使用するときに、多くの人が犯すことになる間違いです! そのため、ルーターで送信する前にそれらを完了する必要があります。
リゾルバを使用してルーターにデータを送信する
上記のセクションで私が何を意味しているかをお見せしましょう。 たとえば、observable:
items: any = ;getData(): Observable<any> { const observable = Observable.create(observer => { observer.next(this.items) }); return observable;}
では、私たちが持っている購読は、決してヒットしないことがわかります。 これは、データを正しく送信していないために起こります。 サブスクリプションを完了できていません。
observer.complete();
プロミスを返す場合、ルーターにデータを送信する前にそれを解決する必要があります。
ルートリゾルバの実装
ルートリゾルバの基本説明と理由および使用方法を終えたら、実装を開始しましょう。 この短い例では、あなたがAngularのCLIコマンドと新しいプロジェクトの作成方法に慣れていることを想定しているので、必須のコードのみをデモします。
この例では、ルートリゾルバによるAPI呼び出しを実演するために、ユーザーデータを取得する偽のAPIとしてjsonplaceholderを使用することにします。
まず最初に、ユーザー データを取得してくれるサービスが必要です。 このサービスには、observable を返す getUsers()
という関数があります。
@Injectable({providedIn: 'root'})export class FakeApiService { constructor(private http: HttpClient) { } private usersEndpoint = "https://jsonplaceholder.typicode.com/users"; getUsers(): Observable<any> { // We do not subscribe here! We let the resolver take care of that... return this.http.get(this.usersEndpoint); }}
重要なのは、関数 getUsers をサブスクライブしないことです。 UserResolverと呼ばれるルートリゾルバがこれを引き受けてくれます。
@Injectable({providedIn: 'root'})export class UserResolverService implements Resolve<any> { constructor(private fakeApi: FakeApiService) { } resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { return this.fakeApi.getUsers().pipe( catchError((error) => { return empty(); }); ); }}
このサービスは getUsers
observable を自動的に購読し、ルーターに取得したデータを提供します。 データの取得中にエラーが発生した場合、空のobservableを送れば、ルータはルートに進まなくなります。
この時点でナビゲーションは終了します。 この最後のステップは、ユーザーが /users
ルートに移動したときに呼び出されるコンポーネントを作成することです。 通常、Resolver がない場合は、コンポーネントの ngOnInit
フックでデータを取得し、「データが存在しない」ことによるエラーを処理する必要があります。 ユーザーのコンポーネントは単純なものです。
ユーザー コンポーネントを作成したら、ルートを定義して、ルーターにリゾルバ ( UserResolver
) を使用するように指示する必要があります。 これは、次のコードを app-routing.modulte.ts
.
const routes: Routes = ;@NgModule({ imports: , exports: })export class AppRoutingModule { }
ユーザーのルートに resolve プロパティを設定し、UserResolver
を宣言することで実現可能です。 データはusersというプロパティを持つオブジェクトに渡されます。 この後、ほぼ完了です。 やらなければならないことはただ一つです。 以下のコードで、ActivatedRoute
を介して取得したデータをusersコンポーネントに取り込む必要があります。
constructor(private activatedRoute: ActivatedRoute) { }users: any;ngOnInit() { this.activatedRoute.data.subscribe((data: { users: any }) => { this.users = data.users; });}
そして、コンポーネントがロードされる前にデータが存在するため、*ngIf
ステートメント(*ngIf="users && users.length > 0
)なしでHTMLに表示するだけでOKです。
<h2>Fetched Users:</h2><ul><li *ngFor="let user of users">{{ user.name }}</li></ul>
まとめ
Route Resolvers に関するこの記事の締めくくりとして、Route Resolvers が私たちにもたらす利点をもう一度指摘しておきたいと思います。 まず、HTML レベルで行わなければならない厄介なチェックを回避し、データを受け取るまで問題が発生しないようにします。 次に、データ取得中にエラーが発生した場合、プレビュー・コンポーネントをロードすることなくナビゲーションを停止できるため、ユーザー・エクスペリエンスに集中することができます。 また、ナビゲーションを完了する前に、ロードされたコンポーネントにアクセスする前に、より多くのロジックをアタッチしたりデータをマッピングしたりすることができます。
デモ コードは GitHub で入手できます。 Angular 7 と RESTEasy フレームワーク.