ほんの数週間前の Angular v19 のリリースは、Input、モデル、出力、およびシグナルクエリ API が正式に安定版に昇格しました。
しかし、それだけではありません!このメジャー バージョンでは、信号革命をさらに前進させるために設計された強力な新しいツール、新しいResource API も導入されています。
名前が示すように、この新しいリソース API は、シグナルの能力を最大限に活用することで 非同期リソース のロードを簡素化するように設計されています。
その仕組みと、非同期リソースの処理がどのように簡素化されるのかを詳しく見てみましょう!重要: の執筆時点では、新しい リソース API はまだ実験段階です。つまり、安定する前に変更される可能性があるため、自己責任で使用してください。 ?
ここで、新しい
Resource API が登場します。
リソースを使用すると、シグナル経由で非同期リソースを簡単に消費できるため、データのフェッチの管理、読み込み状態の処理、関連するシグナル パラメーターが変更されるたびに新しいフェッチのトリガーを簡単に行うことができます。
resource( ) 関数リソースを作成する簡単な方法は、resource() 関数を使用することです。
import { resource, signal } from '@angular/core'; const RESOURCE_URL = 'https://jsonplaceholder.typicode.com/todos/'; private id = signal(1); private myResource = resource({ request: () => ({ id: this.id() }), loader: ({ request }) => fetch(RESOURCE_URL + request.id), });
ResourceOptions 構成オブジェクトを入力として受け入れ、次のプロパティを指定できます。
非同期依存関係 を簡単に定義できます。
リソースが作成されると、loader関数が実行され、その結果として生じる非同期リクエストが開始されます。
import { resource, signal } from '@angular/core'; const RESOURCE_URL = 'https://jsonplaceholder.typicode.com/todos/'; private id = signal(1); private myResource = resource({ request: () => ({ id: this.id() }), loader: ({ request }) => fetch(RESOURCE_URL + request.id), });
request 関数が依存するシグナルが変更されるたびに、request 関数が再度実行され、新しいパラメーターが返された場合は、loader 関数がトリガーされます。更新されたリソースの値を取得するには:
import { resource, signal } from "@angular/core"; const RESOURCE_URL = "https://jsonplaceholder.typicode.com/todos/"; const id = signal(1); const myResource = resource({ request: () => ({ id: id() }), loader: ({ request }) => fetch(RESOURCE_URL + request.id) }); console.log(myResource.status()); // Prints: 2 (which means "Loading")
request 関数が指定されていない場合、reload を使用して Resource が再ロードされない限り、loader 関数は 1 回だけ実行されます。メソッド (詳細は後述)。
最後に、親コンポーネントまたはサービスが破棄されると、特定のインジェクターが提供されていない限り、リソース も破棄されます。
そのような場合、リソースはアクティブなままとなり、提供されたインジェクター自体が破棄された場合にのみ破棄されます。
データのフェッチを最適化するために、前の値がまだロードされている間に request() の計算が変更された場合、リソース は未処理のリクエストを中止できます。
これを管理するために、loader() 関数は、fetch などの進行中のリクエストに渡すことができる abortSignal を提供します。リクエストは abortSignal をリッスンし、トリガーされた場合は操作をキャンセルします。これにより効率的なリソース管理が確保され、不要なネットワーク リクエストが防止されます。
import { resource, signal } from "@angular/core"; const RESOURCE_URL = "https://jsonplaceholder.typicode.com/todos/"; const id = signal(1); const myResource = resource({ request: () => ({ id: id() }), loader: ({ request }) => fetch(RESOURCE_URL + request.id) }); console.log(myResource.status()); // Prints: 2 (which means "Loading") // After the fetch resolves console.log(myResource.status()); // Prints: 4 (which means "Resolved") console.log(myResource.value()); // Prints: { "id": 1 , ... } id.set(2); // Triggers a request, causing the loader function to run again console.log(myResource.status()); // Prints: 2 (which means "Loading") // After the fetch resolves console.log(myResource.status()); // Prints: 4 (which means "Resolved") console.log(myResource.value()); // Prints: { "id": 2 , ... }
これに基づき、通常は問題を引き起こすことなく安全にキャンセルできるため、GET リクエストには主に Resource API を使用することをお勧めします。
POST または UPDATE リクエストの場合、キャンセルすると不完全なデータ送信や更新などの予期しない副作用が発生する可能性があります。ただし、これらのタイプのリクエストに同様の機能が必要な場合は、effect() メソッドを使用して操作を安全に管理できます。
リソース API は、コンポーネントまたはサービス内で直接簡単に使用できる、その状態の信号プロパティをいくつか提供します。
コンポーネント内で リソース を消費する方法の例を次に示します。
import { resource, signal } from '@angular/core'; const RESOURCE_URL = 'https://jsonplaceholder.typicode.com/todos/'; private id = signal(1); private myResource = resource({ request: () => ({ id: this.id() }), loader: ({ request }) => fetch(RESOURCE_URL + request.id), });
この例では、Resource は、id 信号の値に基づいて API からデータをフェッチするために使用されます。
id信号の値は、ボタンをクリックすることで増加できます。 ユーザーがボタンをクリックするたびに、id シグナル値が変化し、
loader関数がトリガーされてリモート API から新しい項目を取得します。
Resourceリソースのステータスを確認する 前述したように、
statusシグナルは、任意の瞬間におけるリソースの現在の状態に関する情報を提供します。 status 信号の可能な値は、
ResourceStatusこれらのステータスは、
リソースの進行状況を追跡し、アプリケーションでの非同期操作の処理を容易にするのに役立ちます。これらのステータスの複雑さを考慮して、リソース API は、現在のステータスに基づいてブール値を返す hasValue() メソッドを提供します。
これにより、リソースのステータスに関する正確な情報が保証され、特定の状態では未定義となる可能性がある値に依存せずに、非同期操作を処理するためのより信頼性の高い方法が提供されます。
import { resource, signal } from '@angular/core'; const RESOURCE_URL = 'https://jsonplaceholder.typicode.com/todos/'; private id = signal(1); private myResource = resource({ request: () => ({ id: this.id() }), loader: ({ request }) => fetch(RESOURCE_URL + request.id), });
このメソッドはリアクティブであるため、シグナル のように消費および追跡できます。
Resource API は、リソースが現在 Loading 状態か Reloading 状態であるかを返す isLoading シグナルも提供します。
import { resource, signal } from "@angular/core"; const RESOURCE_URL = "https://jsonplaceholder.typicode.com/todos/"; const id = signal(1); const myResource = resource({ request: () => ({ id: id() }), loader: ({ request }) => fetch(RESOURCE_URL + request.id) }); console.log(myResource.status()); // Prints: 2 (which means "Loading")
isLoading は計算された信号であるため、事後的に追跡でき、信号 API を使用して読み込み状態をリアルタイムで監視できます。
Resource によって提供される値シグナルは WritableSignal です。これにより、set() と update( ) 関数:
import { resource, signal } from "@angular/core"; const RESOURCE_URL = "https://jsonplaceholder.typicode.com/todos/"; const id = signal(1); const myResource = resource({ request: () => ({ id: id() }), loader: ({ request }) => fetch(RESOURCE_URL + request.id) }); console.log(myResource.status()); // Prints: 2 (which means "Loading") // After the fetch resolves console.log(myResource.status()); // Prints: 4 (which means "Resolved") console.log(myResource.value()); // Prints: { "id": 1 , ... } id.set(2); // Triggers a request, causing the loader function to run again console.log(myResource.status()); // Prints: 2 (which means "Loading") // After the fetch resolves console.log(myResource.status()); // Prints: 4 (which means "Resolved") console.log(myResource.value()); // Prints: { "id": 2 , ... }
注: ご覧のとおり、シグナルの 値 を手動で更新すると、ステータスも 5 に設定されます。これは、「ローカル」を意味します"、値がローカルに設定されたことを示します。
手動で設定した値は、新しい値が設定されるか、新しいリクエストが実行されるまで保持され、新しい値でオーバーライドされます。
import { resource, signal } from "@angular/core"; const RESOURCE_URL = "https://jsonplaceholder.typicode.com/todos/"; const id = signal(1); const myResource = resource({ request: () => ({ id: id() }), loader: ({ request, abortSignal }) => fetch(RESOURCE_URL + request.id, { signal: abortSignal }) }); console.log(myResource.status()); // Prints: 2 (which means "Loading") // Triggers a new request, causing the previous fetch to be aborted // Then the loader function to run again generating a new fetch request id.set(2); console.log(myResource.status()); // Prints: 2 (which means "Loading")
注: リソース API の 値 シグナルは、新しい LinkedSignal API と同じパターンを使用しますが、それはボンネットの下にあります。 ?
value シグナルの使用を簡素化するために、Resource API は、set、update、および asReadonly メソッド。
asReadonly メソッドは、value 信号の読み取り専用インスタンスを返し、読み取りのみのアクセスを許可し、誤った変更を防ぐため、特に便利です。
このアプローチを使用すると、値の読み取り専用インスタンスをエクスポートすることで、リソース値の変更を管理および追跡するサービスを作成できます:
import { Component, resource, signal } from '@angular/core'; const BASE_URL = 'https://jsonplaceholder.typicode.com/todos/'; @Component({ selector: 'my-component', template: ` @if (myResource.value()) { {{ myResource.value().title }} } <button (click)="fetchNext()">Fetch next item</button> ` }) export class MyComponent { private id = signal(1); protected myResource = resource({ request: () => ({ id: this.id() }), loader: ({ request }) => fetch(BASE_URL + request.id).then((response) => response.json()), }); protected fetchNext(): void { this.id.update((id) => id + 1); } }
非同期リソースを操作する場合、データの更新や リソース の破棄が必要になるシナリオに直面する可能性があります。
これらのシナリオを処理するために、リソース API は、これらのアクションを管理するための効率的なソリューションを提供する 2 つの専用メソッドを提供します。
reload() メソッドは、Resource に非同期リクエストを再実行するように指示し、最新のデータを確実にフェッチします。
import { resource, signal } from '@angular/core'; const RESOURCE_URL = 'https://jsonplaceholder.typicode.com/todos/'; private id = signal(1); private myResource = resource({ request: () => ({ id: this.id() }), loader: ({ request }) => fetch(RESOURCE_URL + request.id), });
リロードが正常に開始された場合、reload() メソッドは true を返します。
ステータスがすでに Loading または Reloading である場合など、リロードが不要であるか、ステータスが である場合など、サポートされていないため、リロードを実行できない場合アイドル、メソッドは false を返します。
destroy() メソッドは、Resource を手動で破棄し、リクエストの変更を追跡するために使用されるすべての effect() を破棄し、保留中のリクエストをキャンセルして、ステータスをアイドルにリセットしながら、値を未定義:
import { resource, signal } from "@angular/core"; const RESOURCE_URL = "https://jsonplaceholder.typicode.com/todos/"; const id = signal(1); const myResource = resource({ request: () => ({ id: id() }), loader: ({ request }) => fetch(RESOURCE_URL + request.id) }); console.log(myResource.status()); // Prints: 2 (which means "Loading")
リソースが破棄されると、リクエストの変更や reload() 操作に応答しなくなります。
注: この時点では、value 信号は書き込み可能なままですが、リソース は本来の目的を失い、その機能を果たさなくなり、役に立たなくなります。 。 ?
これまでに紹介したほぼすべてのシグナルベースの API と同様、Resource API も、RxJS とのシームレスな統合のための相互運用性ユーティリティを提供します。
resource() メソッドを使用して Promise ベースの Resource を作成する代わりに、rxResource() メソッドを使用して を使用できます。観測対象:
import { resource, signal } from "@angular/core"; const RESOURCE_URL = "https://jsonplaceholder.typicode.com/todos/"; const id = signal(1); const myResource = resource({ request: () => ({ id: id() }), loader: ({ request }) => fetch(RESOURCE_URL + request.id) }); console.log(myResource.status()); // Prints: 2 (which means "Loading") // After the fetch resolves console.log(myResource.status()); // Prints: 4 (which means "Resolved") console.log(myResource.value()); // Prints: { "id": 1 , ... } id.set(2); // Triggers a request, causing the loader function to run again console.log(myResource.status()); // Prints: 2 (which means "Loading") // After the fetch resolves console.log(myResource.status()); // Prints: 4 (which means "Resolved") console.log(myResource.value()); // Prints: { "id": 2 , ... }
注: rxResource() メソッドは、実際には rxjs-interop パッケージによって公開されています。
loader() 関数によって生成される Observable は、最初に出力された値のみを考慮し、後続の出力は無視します。
この素晴らしい 2024 年を通して私をフォローしていただきありがとうございました。 ??
今年は課題に満ちた年でしたが、とてもやりがいのある年でもありました。私には 2025 年に向けた大きな計画があり、それに取り組み始めるのが待ちきれません。 ?
フィードバックをお待ちしておりますので、コメント、いいね、または フォローをお願いいたします。 ?
本当に気に入った場合は、コミュニティ、技術者仲間、その他好きな人に共有してください。 LinkedIn で私をフォローしてください。 ??
以上がAngular resource() および rxResource() API: 知っておくべきことの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。