---
# System prepended metadata

title: Angular19 Signals + HTTP = httpResource
tags: [Angular, TypeScript]

---

# Angular19 Signals + HTTP = httpResource
==此為翻譯文章，純分享==

Angular 19.2 引入了一個實驗性的新 API，稱為 httpResource。

先從基礎開始談起。隨著 Angular 框架逐步導入 Signals，許多人也開始關注一個問題：既然 HttpClient 是回傳 Observable，那該如何與 Signals 搭配使用？

簡單的答案是：可以使用 toSignal 函式來轉換。

```typescript=
signal = toSignal(this.http.get("http://mydata.com"));
```
雖然上述方法可行，但它無法清楚知道以下狀況：
* 資料是否已載入？是否還在載入中？
* 請求過程中是否發生錯誤？
而 resource API 就解決了這些問題，因為它會回傳一組 Signals 和方法，能夠幫助我們掌握所有這些狀態

![image](https://hackmd.io/_uploads/HyCU8a9Zeg.png)

可以檢查 resource.hasValue() 或 resource.isLoading() 來取得狀態.

## 如何建立 httpResource
建立一個用於 HTTP 請求的 resource 非常簡單：
```typescript=
resource = httpResource('https://dummyjson.com/users');
```
當然，也可以透過 TypeScript 加上類型資訊，來指定從伺服器回傳的資料結構：
```typescript=
resource = httpResource<UserList>('https://dummyjson.com/users');
```
現在，如果我們想要在畫面上顯示從伺服器取得的資料，只需要這樣寫：
```typescript=
@for(user of resource.value()?.users; track user.id) {
  <div class="user">
    {{user.firstName}} {{user.lastName}} - {{user.age}} 歲
  </div>
}
```
而如果想在資料載入期間顯示一個載入動畫（例如 spinner），只需要加上以下程式碼：
```typescript=
@if (resource.isLoading()) {
  <img src="https://i.gifer.com/ZZ5H.webp" width="50px" />
}
```
範例連結：http://stackblitz.com/edit/ng-http-resource-simple?file=src%2Fmain.ts

## HTTP 資源以後還能再被觸發嗎？
答案是：可以，而且最棒的是，這一切都是基於 Signal 的設計！

舉個例子，如果我們需要支援分頁功能，而分頁的資訊是透過 URL 查詢參數來控制的，例如：
```typescript=
// 取得 10 筆使用者資料，跳過前面 20 筆
https://dummyjson.com/users?limit=10&skip=20

```

可以修改 resource 的定義，使其支援動態的 URL 參數。關鍵在於：傳入一個函式作為參數，而不是單純的字串 URL：
```typescript=
resource = httpResource<UserList>(() => ({
  url: `https://json.com/users?limit=${this.pageSize()}&skip=${this.pageSize() * this.page()}`
}));
```
這個範例中，pageSize() 和 page() 都是 Signals，它們的值綁定在一個表單上，使用者可以透過按鈕或下拉選單來變更這些參數：

HTML ：

```typescript=
<div class="controls">
  每頁筆數：
  <select [(ngModel)]="pageSize">
    <option>5</option>
    <option>10</option>
    <option>20</option>
  </select>
  -
  <button (click)="previousPage()">< 上一頁</button>
  第 {{page() + 1}} 頁 / 共 {{totalPages()}} 頁
  <button (click)="nextPage()">下一頁 ></button>
</div>
```

這整個流程在於：當使用者點擊「下一頁」按鈕時，我們只需要更新一個 Signal 的值：
```typescript=
nextPage() {
  this.page.update((page) => page + 1);
}
```
由於 page() 是httpResource 的依賴之一，每次它的值變動時，就會自動重新發送 HTTP 請求以取得最新資料，這就像使用 computed signal 一樣直覺又強大。

範例連結：https://stackblitz.com/edit/ng-http-resource-pagination?file=src%2Fglobal_styles.css

## 想使用 HTTP POST 而不是 GET 怎麼辦？
可以這麼做。當然，它適用於所有類型的 HTTP 請求：
```typescript=
resource = httpResource<UserList>(() => ({
  url: `https://json.com/users?limit=${this.pageSize()}&skip=${this.pageSize() * this.page()}`,
  method: "POST"
 })
);
```

## 如果我的請求中包含動態的 body 或 headers？
很簡單——使用 Signals 就對了！只要這些 Signals 的值有任何變動，就會自動觸發新的 HTTP 請求：
```typescript=
resource = httpResource<UserList>(() => ({
  url: "api/schools/collection/filter",
  method: "POST",
  body: { pageSize: this.pageSize(), page: this.page() }
}));

```
同樣的概念也適用於 headers、params、URL 等其他部分。只要這些欄位中使用的是 Signal，它們的變化就會驅動 resource 重新執行請求。

以下是 HttpResourceRequest 物件所支援的所有選項，也是傳給 httpResource 函式的參數：
![image](https://hackmd.io/_uploads/Sy3QOac-le.png)

值得注意的是，可以手動觸發 resource 的重新載入，並且如果在前一個請求尚未完成時又發起新的請求，httpResource 會自動中止上一個尚未完成的 HTTP 請求。

雖然 httpResource API 目前仍屬於實驗性功能，但它極有可能在不久的將來取代我們所有對 HttpClient 的使用方式——也正因如此，和大家分享這項新功能！

>資料來源出處[Signals + HTTP = httpResource [Tutorial]]
>https://blog.angulartraining.com/signals-http-httpresource-tutorial-bf8792e9bda0