web-dev-qa-db-ja.com

Angularでリゾルバーを使用する理由

resolversのアイデアが好きです。

そうとも言える:
-特定のルートでは、最初に何らかのデータがロードされると予想されます
_this.route.snapshot.data_からデータを取得するように)観測可能なものを持たない、本当にシンプルなコンポーネントを作成できます。

したがって、リゾルバは非常に理にかなっています。

---(ただし:
-実際の応答を受信するまで、URLを変更して要求されたコンポーネントを表示することはありません。そのため、コンポーネントをレンダリングしてできるだけ表示することで(単純に)ユーザーに何かが起こっていることを示すことはできません(推奨されるように、PWAを使用するシェルアプリの場合)。つまり、接続状態が悪い場合、ユーザーは長時間何が起こっているかを視覚的に表示せずに待機する必要がある場合があります
-paramを使用してルートでリゾルバーを使用している場合、_users/1_を例に取りましょう。最初は問題なく動作します。ただし、_users/2_に移動すると、別のobservableを使用し始めない限り、何も起こりません:this.route.data.subscribe()

したがって、リゾルバはいくつかのデータを取得するのに役立つと思われますが、実際には遅いネットワークがあり、特にparamsを持つルートの場合は使用しません。

ここに何かが足りませんか?それらの本当の制約でそれらを使用する方法はありますか?

32
maxime1992

リゾルバー:ユーザーが新しいページにルーティングされる前でも実行されます。

コンポーネントの初期化の前にデータを取得する必要があるときはいつでも、これを行う正しい方法はリゾルバーを使用することです。リゾルバーは同期的に動作します。つまり、リゾルバーは非同期呼び出しが完了するまで待機し、非同期呼び出しを処理した後にのみ、それぞれのURLにルーティングします。したがって、コンポーネントの初期化は、コールバックが完了するまで待機します。したがって、コンポーネントを初期化する前であっても、何か(サービスコール)を行いたい場合は、適切な場所に来ています。

Example Scenario:私は、ユーザーがURLにロードするファイルの名前を渡すプロジェクトに取り組んでいました。渡された名前に基づいて、ngOnInitで非同期呼び出しを行い、ファイルを取得します。しかし、これに伴う問題は、ユーザーがURLに間違った名前を渡すと、サービスがサーバーに存在しないファイルを取得しようとすることです。このようなシナリオには2つのオプションがあります。

オプション1:ngOnInitで有効なファイル名のリストを取得し、実際のサービスを呼び出してファイルを取得します(ファイル名が有効な場合)。 これらの呼び出しは両方とも同期である必要があります。

オプション2:リゾルバーで有効なファイル名のリストを取得し、URLのファイル名が有効かどうかを確認してから、ファイルデータを取得します。

リゾルバーは呼び出しの同期性を処理するため、オプション2の方が適しています。

重要::ユーザーがURLにルーティングされる前でもデータを取得する場合は、リゾルバーを使用します。リゾルバーには、次のページ

6
harsh hundiwala

リゾルバーは、ルーターナビゲーションの開始近くにフックを提供し、ナビゲーションの試行を制御できるようにします。これにより、多くの自由が与えられますが、多くの厳格で速い規則はありません。

コンポーネントで解決の結果を使用する必要はありません。解決策をフックとして使用できます。これは、あなたが引用した理由のためにそれを使用する私の好ましい方法です。コンポーネントで結果を使用する方がはるかに簡単ですが、同期的なトレードオフがあります。

たとえば、MaterialやCdkなどを使用している場合、「ロード」ダイアログをディスパッチして、解決の開始時に進行状況インジケーターを表示し、解決が完了したらダイアログを閉じることができます。そのようです:

constructor(route: ActivatedRouteSnapshot, myService: MyService, dialog: MatDialog) {}

resolve() {
    const dialogRef = this.dialog.open(ProgressComponent);
    return this.myService.getMyImportantData().pipe(
        tap(data => this.myService.storeData(data)),
        tap(() => dialogRef.close()),
        map(() => true),
        catchError(err => of(false))
    );
}

ngrxを使用している場合、解決の進行中にアクションをディスパッチすることで同様のことができます。

この方法でResolveガードを使用している場合、CanActivateガードの代わりにResolveガードを使用する特別な理由はありません。その選択はセマンティクスに帰着します。 CanActivateで認証をゲートし、Resolveからデータ取得を開始することはより明白です。それらのトピックをブレンドすることが許可されている場合、それは不合理な選択になります。

これがリゾルバを使用する理由です:

  • 単一の責任、私のコンポーネントにはいくつかのデータが必要です。場合によっては、このデータはキャッシュまたは状態によって提供されます。 :リストmyapp.com/listsを含む検索結果ページ、リストmyapp.com/lists/1の1つの要素に移動し、その要素の詳細を表示します。データを取得する必要はありません。既に検索によって行われます。次に、フェッチする必要があるmyapp.com/lists/1に直接移動し、コンポーネントに移動するとします。
  • コンポーネントをルーターロジックから分離する
  • 私のコンポーネントはフェッチリクエストの読み込み状態を管理するべきではありません。データを表示することだけが責任です

リゾルバーはアプリとコンポーネントの間のミドルウェアであると考えてください。<router-outlet>が含まれている親コンポーネントで読み込みビューを管理できます。

1
albanx

私は現在、多くのリゾルバーを使用するアプリをリファクタリングし、それらについて多くのことを考え、それらの最大の問題は、データを変更することであると考えています。つまり、アプリのメンテナンスに複雑さと問題が追加されますが、直接サービスインジェクションにはこの問題はありません。

0
Timothy