Angular resource() 和 rxResource() API:您需要了解的內容
幾週前發布的Angular v19 標誌著框架內訊號革命的一個重要里程碑,輸入、模型、輸出和訊號查詢 API現已正式升級為穩定版。
但這還不是全部!這個主要版本也引進了旨在進一步推進訊號革命的強大新工具:新的資源API。
顧名思義,這個新的資源 API 旨在透過充分利用訊號的力量來簡化載入非同步資源!
重要提示:在撰寫本文時,新的資源 API 仍處於實驗階段。這意味著它在變得穩定之前可能會發生變化,因此使用它需要您自擔風險。 ?
讓我們深入了解它的工作原理以及它如何簡化非同步資源的處理!
資源 API
大多數訊號 API 都是同步的,但在實際應用中,處理非同步資源至關重要,例如從伺服器取得資料或即時管理使用者互動。
這就是新的資源 API 發揮作用的地方。
使用資源,您可以輕鬆地透過訊號消耗非同步資源,從而輕鬆管理資料擷取、處理載入狀態,並在相關訊號參數變更時觸發新的擷取。
資源( ) 函數
建立資源更簡單的方法是使用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:一個載入函數,傳回資源值的 Promise,可以選擇基於提供的 request 參數。這是 ResourceOptions; 唯一的 必需的 屬性
- equal:相等函數,用於比較loader的回傳值;
- injector:覆寫 Resource 實例使用的 Injector,以便在父元件或服務被銷毀時銷毀自身。
借助這些配置,我們可以輕鬆定義非同步依賴項,它將始終被有效使用並保持最新。
資源生命週期
一旦建立了資源,就會執行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 函數,則loader 函數將只運行一次,除非使用reload重新載入Resource方法(更多下文)。
最後,一旦父元件或服務被銷毀,資源也會被銷毀,除非提供了特定的注入器。
在這種情況下,資源將保持活動狀態,並且僅當提供的注入器本身被銷毀時才會被銷毀。
使用 abortSignal 中止請求
為了優化資料獲取,如果 request() 計算發生變化而先前的值仍在加載,資源 可以中止未完成的請求。
為了管理此問題,loader() 函數提供了 abortSignal,您可以將其傳遞給正在進行的請求,例如 fetch。此請求監聽 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 為其狀態提供了多個訊號屬性,您可以直接在元件或服務中輕鬆使用它們:
- 值:包含資源的目前值,如果沒有可用值,則包含未定義。作為WritableSignal,可以手動更新;
- 狀態:包含資源的當前狀態,指示資源正在做什麼以及可以從其值中得到什麼;
- 錯誤:如果處於錯誤狀態,則包含資源載入期間引發的最新錯誤;
- isLoading:指示資源是否正在載入新值或重新載入現有值。
以下是如何在元件中使用資源的範例:
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 訊號值都會發生變化,從而觸發 loader 函數從遠端 API 取得新項目。
由於 Resource API 公開的訊號屬性,UI 會自動使用所取得的資料進行更新。
檢查資源的狀態
如前所述,狀態訊號提供有關資源在任何給定時刻的當前狀態的資訊。
status 訊號的可能值由 ResourceStatus 列舉定義。以下是這些狀態及其對應值的摘要:
- 空閒 = 0:資源沒有有效要求,不會執行任何載入。 value() 是 未定義;
- Error = 1:載入失敗並出現錯誤。 value() 是 未定義;
- 正在載入 = 2:由於請求發生更改,資源目前正在載入新值。 value() 是 未定義;
- 正在重新載入 = 3:資源目前正在為相同請求重新載入新值。 value()會繼續傳回先前取得的值,直到重新載入作業完成;
- 已解決=4:載入完成。 value() 包含載入器資料取得程序傳回的值;
- Local = 5:該值是透過 set() 或 update() 在本地設定的。 value() 包含手動指派的值。
這些狀態有助於追蹤資源的進度,並有助於更好地處理應用程式中的非同步操作。
hasValue() 函數
鑑於這些狀態的複雜性,資源 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), });
此方法是響應式的,允許您像訊號一樣使用和追蹤它。
isLoading()函數
Resource API 也提供了 isLoading 訊號,該訊號會傳回資源目前是否處於 Loading 或 Reloading 狀態:
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 即時監控載入狀態。
作為 WritableSignal 的資源值
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")
注意: Resource API 的value 訊號使用與新的LinkedSignal API 相同的模式,但不使用它在引擎蓋下。 ?
便利包裝方法
為了簡化value 訊號的使用,Resource API 為set、update 和updateasReadonly 方法。
asReadonly 方法特別有用,因為它會傳回 value 訊號的唯讀實例,僅允許讀取存取並防止任何意外修改。
您可以使用此方法透過匯出 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 提供了兩種專用方法,為管理這些操作提供有效的解決方案。
重新載入()函數
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。
如果無法執行重新加載,無論是因為沒有必要,例如當狀態已正在加載或正在重新加載,或不支持,例如當狀態為時空閒,該方法回傳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訊號仍然可寫,但Resource將失去其預期目的,不再發揮其功能,變得無用。 ?
rxResource( ) 函數
與迄今為止引入的幾乎所有基於訊號的 API 一樣,資源 API 還提供了一個互通性實用程序,用於與 RxJS 無縫整合。
您可以使用rxResource() 方法來建立基於Promise 的Resource,而不是使用resource() 方法來使用可觀察:
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中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

JavaScript不需要安裝,因為它已內置於現代瀏覽器中。你只需文本編輯器和瀏覽器即可開始使用。 1)在瀏覽器環境中,通過標籤嵌入HTML文件中運行。 2)在Node.js環境中,下載並安裝Node.js後,通過命令行運行JavaScript文件。
