# Angular 20 Resource API, httpResource Ñа пиÑÐ°Ð½Ð½Ñ Ð´Ð»Ñ ÑеÑ
нÑÑниÑ
ÑпÑвбеÑÑд
> ÐеÑалÑний поÑÑбник з Resource API в Angular 20: resource(), rxResource() Ñа httpResource() Ð´Ð»Ñ ÑеакÑивного оÑÑÐ¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ
. ÐалÑдаÑÑÑ Zod, ÑÑÐ´ÐºÐ¾Ð²Ñ ÑÑаÑÑÑи, мÑгÑаÑÑÑ Ð· HttpClient Ñа акÑÑалÑÐ½Ñ Ð¿Ð¸ÑÐ°Ð½Ð½Ñ Ð´Ð»Ñ ÑеÑ
нÑÑниÑ
ÑпÑвбеÑÑд Angular Ñ 2026 ÑоÑÑ.
- Published: 2026-05-30
- Updated: 2026-05-30
- Author: SharpSkill
- Tags: angular, angular-20, resource-api, httpresource, signals, typescript, tutorial
- Reading time: 10 min
---
Angular 20 пеÑеÑвоÑив Resource API з екÑпеÑименÑалÑÐ½Ð¾Ñ ÑÑнкÑÑоналÑноÑÑÑ Ð½Ð° ÑÑабÑлÑний пÑимÑÑив ÑÑеймвоÑкÑ. ÐабÑÑ ÑнÑÑÑÑменÑÑв `resource()`, `rxResource()` Ñа `httpResource()` Ð½Ð°Ð´Ð°Ñ ÑозÑобникам деклаÑаÑÐ¸Ð²Ð½Ñ Ð¼Ð¾Ð´ÐµÐ»Ñ Ð´Ð»Ñ Ð·Ð°Ð²Ð°Ð½ÑаженнÑ, вÑдÑÑÐµÐ¶ÐµÐ½Ð½Ñ Ñа ÑнвалÑдаÑÑÑ Ð°ÑинÑ
ÑонниÑ
даниÑ
, ÑÑÑно ÑнÑегÑÐ¾Ð²Ð°Ð½Ñ Ñз ÑиÑÑÐµÐ¼Ð¾Ñ ÑигналÑв Angular. Ð¦Ñ Ð¿ÑимÑÑиви ÑÑÑваÑÑÑ Ð½ÐµÐ¾Ð±Ñ
ÑднÑÑÑÑ ÑÑÑного кеÑÑÐ²Ð°Ð½Ð½Ñ Ð¿ÑдпиÑками, пÑапоÑÑÑми ÑÑÐ°Ð½Ñ Ð·Ð°Ð²Ð°Ð½ÑÐ°Ð¶ÐµÐ½Ð½Ñ Ñа Ñ
Ñками жиÑÑÑвого ÑÐ¸ÐºÐ»Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½ÑÑв â клаÑиÑними джеÑелами Ð²Ð¸Ð¿Ð°Ð´ÐºÐ¾Ð²Ð¾Ñ ÑкладноÑÑÑ Ð² Angular-заÑÑоÑÑнкаÑ
.
У ÑÑаÑÑÑ Ð´ÐµÑалÑно ÑозглÑдаÑÑÑÑÑ ÑÑи ваÑÑанÑи Resource API, пÑодемонÑÑÑовано пÑакÑиÑÐ½Ñ ÑÑенаÑÑÑ Ð· пÑикладами кодÑ, опиÑано пÑдÑ
Ñд до валÑдаÑÑÑ Ð²ÑдповÑдей ÑеÑвеÑа ÑеÑез Zod Ñа зÑбÑано пиÑаннÑ, Ñо найÑаÑÑÑÑе зÑÑÑÑÑÑаÑÑÑÑÑ Ð½Ð° ÑеÑ
нÑÑниÑ
ÑпÑвбеÑÑдаÑ
Angular Ñ 2026 ÑоÑÑ.
> **Що змÑнилоÑÑ Ð² Angular 20 поÑÑвнÑно з веÑÑÑÑÑ 19**
>
> Resource API вийÑов Ð·Ñ ÑÑадÑÑ developer preview Ñа оÑÑимав ÑÑабÑлÑний ÑÑаÑÑÑ. ÐÐ¾Ð»Ð¾Ð²Ð½Ñ Ð·Ð¼Ñни ÑÑоÑÑÑÑÑÑÑ API: паÑамеÑÑ `request` пеÑейменовано на `params`, а ÑÑнкÑÑÑ `loader` Ñа `stream` замÑнили попеÑÐµÐ´Ð½Ñ Ð½Ð°Ð·Ð²Ð¸ Ñ ÐºÐ¾Ð½ÑÑакÑаÑ
`resource()` Ñа `rxResource()`. ÐÑÑм Ñого, `httpResource` пÑдÑÑимÑÑ Ð½Ð°ÑÐ¸Ð²Ð½Ñ Ð²Ð°Ð»ÑдаÑÑÑ ÑеÑез опÑÑÑ `parse`, а Ñип `ResourceStatus` ÑÐµÐ¿ÐµÑ Ð²Ð¸ÐºÐ¾ÑиÑÑовÑÑ ÑÑÐ´ÐºÐ¾Ð²Ñ Ð»ÑÑеÑали (`'loading'`, `'resolved'`, `'error'`) замÑÑÑÑ ÑиÑлового enum. СеманÑика залиÑаÑÑÑÑÑ Ð½ÐµÐ·Ð¼ÑнноÑ, пÑоÑе ÑинÑакÑÐ¸Ñ Ð¿Ð¾ÑÑебÑÑ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¿Ñи пеÑеÑ
Ð¾Ð´Ñ Ð· Angular 19.
## ТÑи ваÑÑанÑи Resource API: resource, rxResource Ñа httpResource
Resource API в Angular 20 ÑкладаÑÑÑÑÑ Ð· ÑÑÑоÑ
окÑемиÑ
пÑимÑÑивÑв, кожен Ñз ÑкиÑ
ÑозÑаÑ
ований на конкÑеÑний ÑÑенаÑÑй викоÑиÑÑаннÑ. ÐибÑÑ Ð¼Ñж ними визнаÑаÑÑÑÑÑ Ð°ÑÑ
ÑÑекÑÑÑними ÑÑÑеннÑми пÑоÑкÑÑ Ñа вже наÑвними залежноÑÑÑми.
**`resource()`** ÑвлÑÑ ÑÐ¾Ð±Ð¾Ñ ÑÑндаменÑалÑний ваÑÑÐ°Ð½Ñ Ð½Ð° Ð±Ð°Ð·Ñ Promise. ФÑнкÑÑÑ `params` визнаÑÐ°Ñ ÑеакÑÐ¸Ð²Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾ÑÑÑ, а ÑÑнкÑÑÑ `loader` повеÑÑÐ°Ñ `Promise` Ñз ÑезÑлÑÑаÑом. ÐÑи кожнÑй змÑÐ½Ñ Ð·Ð½Ð°ÑеннÑ, Ñке повеÑÑÐ°Ñ `params`, loader запÑÑкаÑÑÑÑÑ Ð¿Ð¾Ð²ÑоÑно, а попеÑеднÑй Ð·Ð°Ð¿Ð¸Ñ Ð°Ð²ÑомаÑиÑно ÑкаÑовÑÑÑÑÑÑ ÑеÑез `AbortSignal`. Цей ваÑÑÐ°Ð½Ñ Ð´Ð¾ÑÑлÑно заÑÑоÑовÑваÑи Ð´Ð»Ñ Ð¿ÑÑмиÑ
викликÑв `fetch()` або ÑнÑегÑаÑÑй Ñз Promise-оÑÑÑнÑованими бÑблÑоÑеками.
**`rxResource()`** пÑизнаÑений Ð´Ð»Ñ ÐºÐ¾Ð´Ð¾Ð²Ð¸Ñ
баз, де акÑивно викоÑиÑÑовÑÑÑÑÑÑ RxJS. ФÑнкÑÑÑ `stream` (Ñ Ð²ÐµÑÑÑÑ 19 називалаÑÑ `loader`) повеÑÑÐ°Ñ `Observable`, а ÑÑеймвоÑк внÑÑÑÑÑнÑо кеÑÑÑ Ð¿ÑдпиÑÐºÐ¾Ñ Ñа вÑдпиÑкоÑ. ÐÑÐ´Ð¿Ð°Ð´Ð°Ñ Ð½ÐµÐ¾Ð±Ñ
ÑднÑÑÑÑ Ñ ÐºÐ¾Ð½ÑÑÑÑкÑÑÑÑ
на кÑÑÐ°Ð»Ñ `takeUntil(this.destroy$)` або ÑÑÑÐ½Ð¾Ð¼Ñ `Subject`. Це ÑÑÑÐµÐ½Ð½Ñ Ð¾Ñобливо випÑавдане, коли логÑка заванÑÐ°Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾ÑÑебÑÑ RxJS-опеÑаÑоÑÑв: `debounceTime`, `switchMap`, `retry` ÑоÑо.
**`httpResource()`** Ñ Ð²Ð¸ÑокоÑÑÐ²Ð½ÐµÐ²Ð¾Ñ ÑпеÑÑалÑзаÑÑÑÑ Ð¿Ð¾Ð²ÐµÑÑ
`HttpClient`. ÐоÑÑаÑнÑо пеÑедаÑи URL або об'ÑÐºÑ ÐºÐ¾Ð½ÑÑгÑÑаÑÑÑ Ð·Ð°Ð¿Ð¸ÑÑ Ñк ÑеакÑÐ¸Ð²Ð½Ñ ÑÑнкÑÑÑ, Ñ ÑÑеймвоÑк ÑамоÑÑÑйно побÑдÑÑ HTTP-виклик Ñз ÑÑаÑ
ÑваннÑм ÑнÑеÑÑепÑоÑÑв Ñа заголовкÑв. Ðа вÑдмÑÐ½Ñ Ð²Ñд `resource()`, ÑÑÑ Ð½Ðµ поÑÑÑбна Ñвна ÑÑнкÑÑÑ `loader`. Саме Ñей ваÑÑÐ°Ð½Ñ Ñекомендовано Ð´Ð»Ñ Ð¿ÐµÑÐµÐ²Ð°Ð¶Ð½Ð¾Ñ Ð±ÑлÑÑоÑÑÑ ÑÑандаÑÑниÑ
ÑÑенаÑÑÑв оÑÑÐ¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ
.
## ÐобÑдова пÑоÑÑÐ»Ñ ÐºÐ¾ÑиÑÑÑваÑа за Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð¾Ñ resource()
ÐаÑÑÑпний пÑиклад ÑлÑÑÑÑÑÑ ÑобоÑÑ `resource()` Ð´Ð»Ñ ÑеакÑивного заванÑÐ°Ð¶ÐµÐ½Ð½Ñ Ð¿ÑоÑÑÐ»Ñ ÐºÐ¾ÑиÑÑÑваÑа. Сигнал `userId` ÑлÑгÑÑ ÑеакÑÐ¸Ð²Ð½Ð¾Ñ Ð·Ð°Ð»ÐµÐ¶Ð½ÑÑÑÑ: змÑна його знаÑÐµÐ½Ð½Ñ Ð°Ð²ÑомаÑиÑно ÑнÑÑÑÑÑ Ð½Ð¾Ð²Ðµ заванÑаженнÑ.
```typescript
// user-profile.component.ts
import { Component, signal, resource } from '@angular/core';
interface User {
id: number;
name: string;
email: string;
}
@Component({
selector: 'app-user-profile',
template: `
@if (userResource.hasValue()) {
{{ userResource.value().name }}
{{ userResource.value().email }}
} @else if (userResource.isLoading()) {
Loading profile...
} @else if (userResource.error()) {
Failed to load user
}
`,
})
export class UserProfileComponent {
userId = signal(1);
// params produces the reactive dependency
// loader receives it and returns a Promise
userResource = resource({
params: () => this.userId(),
loader: async ({ params: id, abortSignal }) => {
const res = await fetch(`/api/users/${id}`, { signal: abortSignal });
return res.json();
},
});
loadUser(id: number) {
this.userId.set(id); // triggers automatic refetch
}
}
```
СÑÑÑ ÑÑого паÑеÑÐ½Ñ Ð¿Ð¾Ð»ÑÐ³Ð°Ñ Ñ ÑÑÑÐºÐ¾Ð¼Ñ ÑозмежÑÐ²Ð°Ð½Ð½Ñ ÑеакÑивниÑ
залежноÑÑей Ñа логÑки заванÑаженнÑ. ФÑнкÑÑÑ `params` виконÑÑÑÑÑÑ Ð²ÑеÑÐµÐ´Ð¸Ð½Ñ ÑеакÑивного конÑекÑÑÑ Angular, ÑÐ¾Ð¼Ñ ÐºÐ¾Ð¶ÐµÐ½ Ñигнал, Ñкий вона зÑиÑÑÑ, авÑомаÑиÑно ÑÑÐ°Ñ Ð²ÑдÑÑежÑÐ²Ð°Ð½Ð¾Ñ Ð·Ð°Ð»ÐµÐ¶Ð½ÑÑÑÑ. Як ÑÑлÑки `userId` набÑÐ²Ð°Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ знаÑеннÑ, ÑÑеймвоÑк пеÑÐµÐ´Ð°Ñ `abortSignal` Ð´Ð»Ñ ÑкаÑÑÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð¿ÐµÑеднÑого запиÑÑ Ð¹ негайно запÑÑÐºÐ°Ñ Ð½Ð¾Ð²Ð¸Ð¹ виклик loader. РозÑÐ¾Ð±Ð½Ð¸ÐºÑ Ð½Ðµ поÑÑÑбно пиÑаÑи жодного ÐºÐ¾Ð´Ñ Ð¾ÑиÑеннÑ.
ÐÐ»Ñ Ð³Ð»Ð¸Ð±Ñого ÑозÑмÑÐ½Ð½Ñ ÑиÑÑеми ÑигналÑв, Ñо лежиÑÑ Ð² оÑÐ½Ð¾Ð²Ñ Resource API, ваÑÑо ознайомиÑиÑÑ Ð· поÑÑбником Ñодо [Angular Signals](/technologies/angular/interview-questions/angular-signals).
## РеакÑивне оÑÑÐ¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ
ÑеÑез httpResource
`httpResource` ÑпÑоÑÑÑ Ð¿Ð°ÑеÑн Ñе бÑлÑÑе, позбавлÑÑÑи вÑд необÑ
ÑдноÑÑÑ Ð¿Ð¸ÑаÑи ÑÑнкÑÑÑ loader. ФÑеймвоÑк ÑамоÑÑÑйно ÑоÑмÑÑ HTTP-запиÑ, викоÑиÑÑовÑÑÑи `HttpClient` Ñазом з ÑнÑеÑÑепÑоÑами, налаÑÑованими Ñ Ð·Ð°ÑÑоÑÑнкÑ.
```typescript
// product-list.component.ts
import { Component, signal, computed } from '@angular/core';
import { httpResource } from '@angular/common/http';
interface Product {
id: number;
name: string;
price: number;
category: string;
}
@Component({
selector: 'app-product-list',
template: `
@if (products.hasValue()) {
@for (product of products.value(); track product.id) {
{{ product.name }}
{{ product.price | currency }}
}
} @else if (products.isLoading()) {
Loading products...
}
`,
})
export class ProductListComponent {
category = signal('electronics');
// httpResource re-fetches whenever category() changes
products = httpResource(() => ({
url: '/api/products',
params: { category: this.category() },
}));
filterByCategory(cat: string) {
this.category.set(cat); // pending request is cancelled, new one starts
}
}
```
ÐÑи Ð²Ð¸ÐºÐ»Ð¸ÐºÑ `filterByCategory()` Ñигнал `category` оновлÑÑÑÑÑÑ. ФÑнкÑÑÑ ÐºÐ¾Ð½ÑÑгÑÑаÑÑÑ, пеÑедана до `httpResource`, зÑиÑÑÑ `this.category()`, ÑÐ¾Ð¼Ñ ÑÑеймвоÑк ÑÑкÑÑÑ Ð·Ð¼ÑÐ½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾ÑÑÑ, ÑкаÑовÑÑ Ð¿Ð¾ÑоÑний HTTP-Ð·Ð°Ð¿Ð¸Ñ Ñ Ð·Ð°Ð¿ÑÑÐºÐ°Ñ Ð½Ð¾Ð²Ð¸Ð¹ з акÑÑалÑними паÑамеÑÑами. Ðа поведÑÐ½ÐºÐ¾Ñ Ñе аналогÑÑно опеÑаÑоÑÑ `switchMap` Ñ RxJS, пÑоÑе без додаÑкового ÑинÑакÑиÑного наванÑаженнÑ.
> **httpResource пÑаÑÑÑ Ð»Ð¸Ñе на ÑиÑаннÑ**
>
> httpResource ÑозÑоблений виклÑÑно Ð´Ð»Ñ Ð¾Ð¿ÐµÑаÑÑй ÑиÑÐ°Ð½Ð½Ñ (GET-запиÑи). ÐеÑоди POST, PUT Ñа DELETE не пÑдÑÑимÑÑÑÑÑÑ. ÐÐ»Ñ Ð¾Ð¿ÐµÑаÑÑй запиÑÑ ÑлÑд викоÑиÑÑовÑваÑи `HttpClient` напÑÑÐ¼Ñ Ð°Ð±Ð¾ ÑеÑвеÑÐ½Ñ Ð´ÑÑ. Ðиклик `.set()` або `.update()` на resource змÑнÑÑ Ð»Ð¸Ñе локалÑне знаÑÐµÐ½Ð½Ñ ÑÐ¸Ð³Ð½Ð°Ð»Ñ Ð±ÐµÐ· вÑдпÑÐ°Ð²Ð»ÐµÐ½Ð½Ñ Ð±ÑдÑ-Ñкого запиÑÑ Ð½Ð° ÑеÑвеÑ.
## ÐалÑдаÑÑÑ ÑÑ
еми за Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð¾Ñ Zod Ñа httpResource
Ðдна з ÑиповиÑ
пÑоблем пÑи оÑÑÐ¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ
на ÑÑонÑÐµÐ½Ð´Ñ â ÑозбÑжнÑÑÑÑ Ð¼Ñж ÑÑÑÑкÑÑÑоÑ, ÑÐºÑ Ð¾ÑÑкÑÑ ÐºÐ»ÑÑнÑÑÑкий код, Ñа ÑÑÑÑкÑÑÑоÑ, ÑÐºÑ ÑакÑиÑно повеÑÑÐ°Ñ ÑеÑвеÑ. Angular 20 Ñозв'ÑзÑÑ ÑÑ Ð¿ÑÐ¾Ð±Ð»ÐµÐ¼Ñ ÑеÑез ÑнÑегÑаÑÑÑ Ð¼ÐµÑ
анÑÐ·Ð¼Ñ Ð²Ð°Ð»ÑдаÑÑÑ Ð±ÐµÐ·Ð¿Ð¾ÑеÑеднÑо Ñ `httpResource` завдÑки опÑÑÑ `parse`.
ÐикоÑиÑÑÐ°Ð½Ð½Ñ [Zod](https://zod.dev) дозволÑÑ Ð¾Ð³Ð¾Ð»Ð¾ÑиÑи оÑÑкÑÐ²Ð°Ð½Ñ ÑÑ
ÐµÐ¼Ñ Ñа валÑдÑваÑи ÐºÐ¾Ð¶Ð½Ñ Ð²ÑдповÑÐ´Ñ Ð°Ð²ÑомаÑиÑно пеÑед Ñим, Ñк Ð´Ð°Ð½Ñ ÑÑанÑÑÑ Ð´Ð¾ÑÑÑпними Ñ ÑаблонÑ. ЯкÑо валÑдаÑÑÑ Ð·Ð°Ð·Ð½Ð°Ñ Ð½ÐµÐ²Ð´Ð°ÑÑ, resource пеÑеÑ
одиÑÑ Ñ ÑÑан `error` з деÑалÑним опиÑом поÑÑÑеннÑ, Ñо ÑнеможливлÑÑ ÑендеÑинг некоÑекÑниÑ
даниÑ
.
```typescript
// order.component.ts
import { Component, signal } from '@angular/core';
import { httpResource } from '@angular/common/http';
import { z } from 'zod';
// Define the expected shape with Zod
const OrderSchema = z.object({
id: z.number(),
status: z.enum(['pending', 'shipped', 'delivered', 'cancelled']),
total: z.number().positive(),
items: z.array(z.object({
productId: z.number(),
quantity: z.number().int().positive(),
unitPrice: z.number().positive(),
})),
createdAt: z.string().datetime(),
});
type Order = z.infer;
@Component({
selector: 'app-order',
template: `
@if (order.hasValue()) {
Order #{{ order.value().id }}
Status: {{ order.value().status }}
Total: {{ order.value().total | currency }}
} @else if (order.error()) {
Invalid order data received
}
`,
})
export class OrderComponent {
orderId = signal(42);
// parse validates the response before exposing it as a signal
order = httpResource(
() => `/api/orders/${this.orderId()}`,
{ parse: OrderSchema.parse }
);
}
```
ÐÑÐ¾Ð±Ð»Ð¸Ð²Ñ ÑÑннÑÑÑÑ Ñей паÑеÑн Ð¼Ð°Ñ Ñ ÐºÐ¾ÑпоÑаÑивниÑ
ÑеÑедовиÑаÑ
, де API ÑÑвоÑÑÑÑÑÑÑ Ð¾ÐºÑемими командами, а ÑÑÑÑкÑÑÑа вÑдповÑдей може змÑнÑваÑиÑÑ Ð±ÐµÐ· попеÑедженнÑ. Runtime-валÑдаÑÑÑ ÑеÑез Zod дÑÑ Ñк конÑÑÐ°ÐºÑ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ мÑж ÑÑонÑендом Ñа бекендом, забезпеÑÑÑÑи негайне виÑÐ²Ð»ÐµÐ½Ð½Ñ Ð½ÐµÑÑмÑÑноÑÑей.
## rxResource Ð·Ñ stream Ñа params
У ÑÑенаÑÑÑÑ
, Ñо поÑÑебÑÑÑÑ RxJS-опеÑаÑоÑÑв â напÑиклад, поле поÑÑÐºÑ Ð· debounce â `rxResource` пÑопонÑÑ ÑнÑеÑÑÐµÐ¹Ñ Ð½Ð° оÑÐ½Ð¾Ð²Ñ Observable. ФÑнкÑÑÑ `stream` (пеÑейменована з `loader` в Angular 20) оÑÑимÑÑ ÑеакÑÐ¸Ð²Ð½Ñ Ð¿Ð°ÑамеÑÑи Ñа повеÑÑÐ°Ñ Observable, Ñким ÑÑеймвоÑк кеÑÑÑ ÑамоÑÑÑйно.
```typescript
// search.component.ts
import { Component, signal } from '@angular/core';
import { rxResource } from '@angular/core/rxjs-interop';
import { HttpClient } from '@angular/common/http';
import { inject } from '@angular/core';
import { debounceTime, switchMap } from 'rxjs';
interface SearchResult {
id: number;
title: string;
excerpt: string;
}
@Component({
selector: 'app-search',
template: `
@if (results.isLoading()) {
Searching...
}
@if (results.hasValue()) {
@for (item of results.value(); track item.id) {
{{ item.title }}
}
}
`,
})
export class SearchComponent {
private http = inject(HttpClient);
query = signal('');
// params (was "request") provides the reactive input
// stream (was "loader") returns an Observable
results = rxResource({
params: () => this.query(),
stream: ({ params: q }) =>
this.http.get('/api/search', {
params: { q },
}),
});
}
```
ÐÑинÑипова вÑдмÑннÑÑÑÑ `rxResource` вÑд `resource` полÑÐ³Ð°Ñ Ñ ÑÐ¸Ð¿Ñ Ð¿Ð¾Ð²ÐµÑненнÑ: `Observable` замÑÑÑÑ `Promise`. Angular беÑе на Ñебе кеÑÑÐ²Ð°Ð½Ð½Ñ Ð¿ÑдпиÑкоÑ, авÑомаÑиÑне ÑкаÑÑÐ²Ð°Ð½Ð½Ñ Ð¿Ñи змÑÐ½Ñ Ð¿Ð°ÑамеÑÑÑв Ñа ÑинÑ
ÑонÑзаÑÑÑ Ð· Ñиклом change detection. ÐÐ»Ñ Ð¿ÑоÑкÑÑв, де вже ÑиÑоко заÑÑоÑовÑÑÑÑÑÑ RxJS Ñа `HttpClient`, Ñаме `rxResource` Ñ Ð½Ð°Ð¹Ð¾ÑганÑÑнÑÑим ÑлÑÑ
ом мÑгÑаÑÑÑ.
## ÐÑдÑÑÐµÐ¶ÐµÐ½Ð½Ñ ÑÑаÑÑÑÑ: ÑÑÐ´ÐºÐ¾Ð²Ñ Ð»ÑÑеÑали замÑÑÑÑ enum
Ðожен екземплÑÑ resource Ð½Ð°Ð´Ð°Ñ Ñигнал `status()`, Ñо повеÑÑÐ°Ñ ÑÑдковий лÑÑеÑал Ñз поÑоÑним ÑÑаном заванÑаженнÑ. Цей пÑдÑ
Ñд замÑнив ÑиÑÐ»Ð¾Ð²Ñ enum з попеÑеднÑÑ
веÑÑÑй, покÑаÑивÑи ÑиÑабелÑнÑÑÑÑ ÐºÐ¾Ð´Ñ Ñа зÑÑÑнÑÑÑÑ Ð²Ð¸ÐºÐ¾ÑиÑÑÐ°Ð½Ð½Ñ Ð· конÑÑÑÑкÑÑÑÑ `@switch` Ñ ÑаблонаÑ
.
| Status | ÐнаÑÐµÐ½Ð½Ñ |
|---|---|
| `'idle'` | `params` повеÑнÑв `undefined` â Ð·Ð°Ð¿Ð¸Ñ Ð½Ðµ надÑилаÑÑÑÑÑ |
| `'loading'` | ÐеÑÑий Ð·Ð°Ð¿Ð¸Ñ Ð²Ð¸ÐºÐ¾Ð½ÑÑÑÑÑÑ |
| `'reloading'` | ÐовÑоÑний Ð·Ð°Ð¿Ð¸Ñ Ð¿ÑÑÐ»Ñ Ð¿Ð¾Ð¿ÐµÑеднÑого ÑÑпÑÑного ÑезÑлÑÑаÑÑ |
| `'resolved'` | ÐÐ°Ð½Ñ Ð´Ð¾ÑÑÑÐ¿Ð½Ñ ÑеÑез `value()` |
| `'error'` | ÐÐ°Ð¿Ð¸Ñ Ð·Ð°Ð²ÐµÑÑивÑÑ Ð½ÐµÐ²Ð´Ð°ÑÐµÑ â `error()` мÑÑÑиÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÑ |
| `'local'` | ÐнаÑÐµÐ½Ð½Ñ Ð²ÑÑановлено локалÑно ÑеÑез `.set()` або `.update()` |
РозмежÑÐ²Ð°Ð½Ð½Ñ `'loading'` Ñа `'reloading'` Ð´Ð°Ñ Ð·Ð¼Ð¾Ð³Ñ Ð±ÑдÑваÑи диÑеÑенÑÑÐ¹Ð¾Ð²Ð°Ð½Ñ UX-паÑеÑни: повноекÑанний ÑкелеÑон пÑи пеÑÑÐ¾Ð¼Ñ Ð·Ð°Ð²Ð°Ð½ÑÐ°Ð¶ÐµÐ½Ð½Ñ Ñа непомÑÑний ÑндикаÑÐ¾Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¿Ñи пеÑезаванÑаженнÑ, коли попеÑÐµÐ´Ð½Ñ Ð´Ð°Ð½Ñ Ð·Ð°Ð»Ð¸ÑаÑÑÑÑÑ Ð²Ð¸Ð´Ð¸Ð¼Ð¸Ð¼Ð¸.
```typescript
// status-demo.component.ts
import { Component, signal, resource } from '@angular/core';
@Component({
selector: 'app-status-demo',
template: `
Status: {{ data.status() }}
@switch (data.status()) {
@case ('loading') { }
@case ('reloading') { }
@case ('resolved') { }
@case ('error') { }
@case ('idle') { Select a filter to load data
}
}
`,
})
export class StatusDemoComponent {
filter = signal(undefined);
data = resource({
params: () => this.filter(),
loader: async ({ params: f, abortSignal }) => {
const res = await fetch(`/api/data?filter=${f}`, { signal: abortSignal });
return res.json();
},
});
}
```
ÐкÑÐµÐ¼Ð¾Ñ Ñваги заÑлÑговÑÑ ÑÑан `'idle'`: коли ÑÑнкÑÑÑ `params` повеÑÑÐ°Ñ `undefined`, resource не ÑнÑÑÑÑÑ Ð¶Ð¾Ð´Ð½Ð¾Ð³Ð¾ запиÑÑ. Цей паÑеÑн ÑеалÑзÑÑ Ñмовне заванÑаженнÑ, де Ð´Ð°Ð½Ñ Ð·Ð°Ð¿Ð¸ÑÑÑÑÑÑÑ Ð· ÑеÑвеÑа лиÑе пÑÑÐ»Ñ ÐºÐ¾Ð½ÐºÑеÑÐ½Ð¾Ñ Ð´ÑÑ ÐºÐ¾ÑиÑÑÑваÑа â обÑÐ°Ð½Ð½Ñ ÑÑлÑÑÑа, каÑегоÑÑÑ Ñи елеменÑа ÑпиÑкÑ.
> **ÐбеÑежно з value() Ñ ÑÑÐ°Ð½Ñ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ¸**
>
> ÐеÑод `value()` генеÑÑÑ Ð²Ð¸ÐºÐ»ÑÑеннÑ, ÑкÑо resource пеÑебÑÐ²Ð°Ñ Ñ ÑÑÐ°Ð½Ñ `'error'`. ÐÐ»Ñ Ð±ÐµÐ·Ð¿ÐµÑного доÑÑÑÐ¿Ñ Ð´Ð¾ даниÑ
ÑлÑд заÑÑоÑовÑваÑи `hasValue()` Ñк Ñмовний заÑ
иÑÑ Ñ ÑÐ°Ð±Ð»Ð¾Ð½Ñ Ð°Ð±Ð¾ меÑод `value.asReadonly()`, Ñкий повеÑне `undefined` за вÑдÑÑÑноÑÑÑ Ð´Ð°Ð½Ð¸Ñ
. Таке пÑоÑкÑне ÑÑÑÐµÐ½Ð½Ñ Ð·Ð¼ÑÑÑÑ ÑозÑобника Ñвно обÑоблÑÑи Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ¾Ð²Ñ ÑÑани, запобÑгаÑÑи Ð²Ð¸Ð¿Ð°Ð´ÐºÐ¾Ð²Ð¾Ð¼Ñ ÑендеÑÐ¸Ð½Ð³Ñ Ð½ÐµÐ²Ð°Ð»ÑдниÑ
даниÑ
.
## ÐиÑÐ°Ð½Ð½Ñ Ð´Ð»Ñ ÑпÑвбеÑÑд з Angular 20 Resource API
ÐижÑе наведено пиÑаннÑ, ÑÐºÑ Ð½Ð°Ð¹ÑаÑÑÑÑе поÑÑÑÑÑÑÑÑÑ Ð½Ð° ÑеÑ
нÑÑниÑ
ÑпÑвбеÑÑдаÑ
Ð´Ð»Ñ Ð¿Ð¾Ð·Ð¸ÑÑй Angular-ÑозÑобникÑв Ñ 2026 ÑоÑÑ. ÐÑдповÑÐ´Ñ Ð¼Ð°ÑÑÑ Ð´Ð¾ÑÑаÑÐ½Ñ Ð³Ð»Ð¸Ð±Ð¸Ð½Ñ Ð´Ð»Ñ Ð´ÐµÐ¼Ð¾Ð½ÑÑÑаÑÑÑ Ð¿ÑакÑиÑного володÑÐ½Ð½Ñ Resource API.
**ÐиÑÐ°Ð½Ð½Ñ 1: Яка ÑÑзниÑÑ Ð¼Ñж resource(), rxResource() Ñа httpResource() в Angular 20?**
`resource()` Ñ Ð±Ð°Ð·Ð¾Ð²Ð¸Ð¼ пÑимÑÑивом, Ñо пÑÐ¸Ð¹Ð¼Ð°Ñ ÑÑнкÑÑÑ `loader`, Ñка повеÑÑÐ°Ñ `Promise`. `rxResource()` пÑизнаÑений Ð´Ð»Ñ RxJS: ÑÑнкÑÑÑ `stream` повеÑÑÐ°Ñ `Observable`. `httpResource()` ÑвлÑÑ ÑÐ¾Ð±Ð¾Ñ Ð²Ð¸ÑокоÑÑÐ²Ð½ÐµÐ²Ñ Ð°Ð±ÑÑÑакÑÑÑ Ð½Ð°Ð´ `HttpClient`, де доÑÑаÑнÑо вказаÑи URL Ñа паÑамеÑÑи запиÑÑ. УÑÑ ÑÑи ваÑÑанÑи авÑомаÑиÑно вÑдÑÑежÑÑÑÑ ÑеакÑÐ¸Ð²Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾ÑÑÑ ÑеÑез `params`, ÑкаÑовÑÑÑÑ Ð°ÐºÑÐ¸Ð²Ð½Ñ Ð·Ð°Ð¿Ð¸Ñи пÑи змÑÐ½Ñ Ð¿Ð°ÑамеÑÑÑв Ñа надаÑÑÑ ÑÑан ÑеÑез Ñигнали `value()`, `status()`, `error()` Ñа `isLoading()`. ÐибÑÑ Ð·Ð°Ð»ÐµÐ¶Ð¸ÑÑ Ð²Ñд конÑекÑÑÑ: `httpResource` Ð´Ð»Ñ ÑÑандаÑÑниÑ
ÑÑенаÑÑÑв, `resource` Ð´Ð»Ñ Ð½Ðµ-HTTP джеÑел, `rxResource` Ð´Ð»Ñ Ð»Ð¾Ð³Ñки з RxJS-опеÑаÑоÑами.
**ÐиÑÐ°Ð½Ð½Ñ 2: Як Angular ÑеалÑзÑÑ Ð°Ð²ÑомаÑиÑне ÑкаÑÑÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸ÑÑв Ñ Resource API?**
ÐÑи змÑÐ½Ñ Ð·Ð½Ð°ÑеннÑ, Ñо повеÑÑаÑÑÑÑÑ ÑÑнкÑÑÑÑ `params()`, ÑÑеймвоÑк авÑомаÑиÑно ÑкаÑовÑÑ Ð¿Ð¾ÑоÑний запиÑ. У Ð²Ð¸Ð¿Ð°Ð´ÐºÑ `resource()` Ñе вÑдбÑваÑÑÑÑÑ ÑеÑез `AbortSignal`, пеÑеданий Ñ `loader`, Ñкий пÑипинÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ `fetch()`. ÐÐ»Ñ `rxResource()` ÑÑеймвоÑк здÑйÑнÑÑ Ð²ÑдпиÑÐºÑ Ð²Ñд поÑоÑного Observable пеÑед ÑÑвоÑеннÑм нового â поведÑнка, аналогÑÑна `switchMap`. ÐÐ»Ñ `httpResource()` ÑкаÑÑÐ²Ð°Ð½Ð½Ñ ÐºÐµÑÑÑÑÑÑÑ Ð²Ð½ÑÑÑÑÑнÑми меÑ
анÑзмами `HttpClient`. Це запобÑÐ³Ð°Ñ Ð¿ÐµÑегоновим Ñмовам (race conditions), коли повÑлÑнÑÑа вÑдповÑÐ´Ñ Ð¼Ð¾Ð¶Ðµ виÑÑÑниÑи акÑÑалÑнÑÑÑ â ÑвиÑе, вÑдоме Ñк "stale response override".
**ÐиÑÐ°Ð½Ð½Ñ 3: Що вÑдбÑваÑÑÑÑÑ, коли params() повеÑÑÐ°Ñ undefined?**
Ðоли `params()` повеÑÑÐ°Ñ `undefined`, resource пеÑеÑ
одиÑÑ Ñ ÑÑан `'idle'` Ñ Ð½Ðµ ÑнÑÑÑÑÑ HTTP-запиÑ. Це паÑеÑн Ñмовного заванÑаженнÑ: resource залиÑаÑÑÑÑÑ Ð½ÐµÐ°ÐºÑивним, доки не бÑдÑÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ñ Ð½ÐµÐ¾Ð±Ñ
ÑÐ´Ð½Ñ Ð¿ÐµÑедÑмови. ÐапÑиклад, ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ Ð´ÐµÑалей може повеÑÑаÑи `undefined`, поки жоден ÐµÐ»ÐµÐ¼ÐµÐ½Ñ Ð½Ðµ обÑано, Ñ ÑозпоÑинаÑи заванÑÐ°Ð¶ÐµÐ½Ð½Ñ Ð»Ð¸Ñе пÑÑÐ»Ñ Ð²Ð¸Ð±Ð¾ÑÑ. СÑан `'idle'` пÑинÑипово вÑдÑÑзнÑÑÑÑÑÑ Ð²Ñд `'loading'`: жоден Ð·Ð°Ð¿Ð¸Ñ Ð½Ðµ виконÑÑÑÑÑÑ Ð¹ не планÑÑÑÑÑÑ, доки `params()` не повеÑне визнаÑене знаÑеннÑ.
**ÐиÑÐ°Ð½Ð½Ñ 4: Як ÑнÑегÑÑÑÑÑÑÑ Zod-валÑдаÑÑÑ Ð· httpResource?**
ÐпÑÑÑ `parse` в `httpResource` пÑÐ¸Ð¹Ð¼Ð°Ñ ÑÑнкÑÑÑ Ð²Ð°Ð»ÑдаÑÑÑ, Ñка виконÑÑÑÑÑÑ Ð½Ð°Ð´ HTTP-вÑдповÑÐ´Ð´Ñ Ð´Ð¾ Ñого, Ñк знаÑÐµÐ½Ð½Ñ ÑÑане доÑÑÑпним ÑеÑез Ñигнал `value()`. ÐеÑедаÑÑи `OrderSchema.parse`, ÐºÐ¾Ð¶Ð½Ñ Ð²ÑдповÑÐ´Ñ Ð±Ñде пеÑевÑÑено вÑдповÑдно до визнаÑÐµÐ½Ð¾Ñ Zod-ÑÑ
еми. ЯкÑо валÑдаÑÑÑ Ð½Ðµ пÑойде, resource пеÑейде Ñ ÑÑан `'error'`, а `error()` мÑÑÑиÑиме об'ÑÐºÑ `ZodError` Ñз пеÑелÑком поÑÑÑенÑ. Цей пÑдÑ
Ñд ÑакÑиÑно впÑоваджÑÑ runtime-конÑÑÐ°ÐºÑ Ð¼Ñж ÑÑонÑендом Ñ Ð±ÐµÐºÐµÐ½Ð´Ð¾Ð¼, Ñо Ð¼Ð°Ñ ÐºÑиÑиÑне знаÑеннÑ, коли API ÑозвиваÑÑÑÑÑ Ð½ÐµÐ·Ð°Ð»ÐµÐ¶Ð½Ð¸Ð¼Ð¸ командами й змÑни ÑÑ
еми можÑÑÑ Ð²ÑдбÑваÑиÑÑ Ð±ÐµÐ· попеÑеднÑÐ¾Ñ ÐºÐ¾Ð¾ÑдинаÑÑÑ.
**ÐиÑÐ°Ð½Ð½Ñ 5: Чим ÑÑан 'loading' вÑдÑÑзнÑÑÑÑÑÑ Ð²Ñд 'reloading' Ñ ResourceStatus?**
СÑан `'loading'` ÑигналÑзÑÑ, Ñо виконÑÑÑÑÑÑ Ð¿ÐµÑÑий Ð·Ð°Ð¿Ð¸Ñ Ñ Ð¶Ð¾Ð´Ð½Ð¸Ñ
попеÑеднÑÑ
даниÑ
Ñ resource немаÑ. СÑан `'reloading'` ознаÑаÑ, Ñо новий Ð·Ð°Ð¿Ð¸Ñ ÑозпоÑаÑо пÑÑÐ»Ñ Ð¿Ð¾Ð¿ÐµÑеднÑого ÑÑпÑÑ
Ñ: попеÑÐµÐ´Ð½Ñ Ð·Ð½Ð°ÑÐµÐ½Ð½Ñ Ð·Ð°Ð»Ð¸ÑаÑÑÑÑÑ Ð´Ð¾ÑÑÑпним ÑеÑез `value()` пÑд ÑÐ°Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ запиÑÑ. Ð¦Ñ Ð²ÑдмÑннÑÑÑÑ Ð´Ð¾Ð·Ð²Ð¾Ð»ÑÑ Ð±ÑдÑваÑи ÑÑÐ·Ð½Ñ UX-паÑеÑни: skeleton-loader або повноекÑанний ÑпÑÐ½Ð½ÐµÑ Ð¿Ñд ÑÐ°Ñ Ð¿ÐµÑÑого заванÑаженнÑ, а пÑи пеÑезаванÑÐ°Ð¶ÐµÐ½Ð½Ñ â диÑкÑеÑний ÑндикаÑÐ¾Ñ (пÑогÑеÑ-баÑ, Ñконка обеÑÑаннÑ) Ñз збеÑеженнÑм Ñже вÑдобÑажениÑ
даниÑ
, Ñо запобÑÐ³Ð°Ñ Ð¼ÐµÑеÑ
ÑÑÐ½Ð½Ñ Ð¿Ð¾ÑожнÑого вмÑÑÑÑ.
ÐодаÑÐºÐ¾Ð²Ñ Ð¿Ð¸ÑÐ°Ð½Ð½Ñ Ñодо ÑигналÑв Ñа SSR в Angular ÑозглÑнÑÑо Ñ ÑÑаÑÑÑ Ð¿Ñо [пиÑÐ°Ð½Ð½Ñ Ð´Ð»Ñ ÑпÑвбеÑÑд з Angular 19](/blog/angular/angular-19-interview-questions-signals-ssr-must-know).
## ÐÑгÑаÑÑÑ Ð· пÑдпиÑок HttpClient на httpResource
Resource API каÑдиналÑно ÑкоÑоÑÑÑ Ð¾Ð±ÑÑг кодÑ, поÑÑÑбного Ð´Ð»Ñ Ð¾ÑÑÐ¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ
, поÑÑвнÑно з клаÑиÑним пÑдÑ
одом на оÑÐ½Ð¾Ð²Ñ ÑÑÑниÑ
пÑдпиÑок до `HttpClient`. ÐижÑе наведено поÑÑвнÑннÑ, Ñке наоÑно демонÑÑÑÑÑ ÑÑÑÐ½ÐµÐ½Ð½Ñ Ñаблонного ÐºÐ¾Ð´Ñ Ñа Ñвного кеÑÑÐ²Ð°Ð½Ð½Ñ Ð¶Ð¸ÑÑÑвим Ñиклом.
```typescript
// BEFORE: manual subscription in ngOnInit
@Component({ /* ... */ })
export class BeforeComponent implements OnInit, OnDestroy {
private http = inject(HttpClient);
private destroy$ = new Subject();
users: User[] = [];
loading = false;
error: string | null = null;
ngOnInit() {
this.loading = true;
this.http.get('/api/users')
.pipe(takeUntil(this.destroy$))
.subscribe({
next: (data) => { this.users = data; this.loading = false; },
error: (err) => { this.error = err.message; this.loading = false; },
});
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
}
// AFTER: httpResource handles lifecycle automatically
@Component({ /* ... */ })
export class AfterComponent {
users = httpResource(() => '/api/users');
// No ngOnInit, no Subject, no manual unsubscribe
// Template uses users.value(), users.isLoading(), users.error()
}
```
ÐÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ Ñ Ð²Ð°ÑÑанÑÑ "before" поÑÑебÑÑ ÑеалÑзаÑÑÑ `OnInit` Ð´Ð»Ñ ÑнÑÑÑÑÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸ÑÑ, `Subject` Ð´Ð»Ñ ÑкаÑÑÐ²Ð°Ð½Ð½Ñ Ð¿ÑдпиÑки, окÑемиÑ
змÑнниÑ
Ð´Ð»Ñ Ð´Ð°Ð½Ð¸Ñ
, ÑÑÐ°Ð½Ñ Ð·Ð°Ð²Ð°Ð½ÑÐ°Ð¶ÐµÐ½Ð½Ñ Ñа помилки, а Ñакож `OnDestroy` Ð´Ð»Ñ Ð·Ð°Ð¿Ð¾Ð±ÑÐ³Ð°Ð½Ð½Ñ Ð²Ð¸Ñокам пам'ÑÑÑ. ÐаÑÑÐ°Ð½Ñ "after" зводиÑÑ ÑÑÑ ÑÑ Ð»Ð¾Ð³ÑÐºÑ Ð´Ð¾ одного деклаÑаÑивного ÑÑдка. ФÑеймвоÑк внÑÑÑÑÑнÑо беÑе на Ñебе ÑнÑÑÑÑÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸ÑÑ, вÑдÑÑÐµÐ¶ÐµÐ½Ð½Ñ ÑÑанÑ, ÑкаÑÑÐ²Ð°Ð½Ð½Ñ Ñа оÑиÑÐµÐ½Ð½Ñ ÑеÑÑÑÑÑв пÑи зниÑÐµÐ½Ð½Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñа.
ÐÑобливо вÑдÑÑÑний еÑÐµÐºÑ ÑÑ Ð¼ÑгÑаÑÑÑ Ð´Ð°Ñ Ñ Ð²ÐµÐ»Ð¸ÐºÐ¸Ñ
кодовиÑ
базаÑ
, де ÑоÑÐ½Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½ÑÑв побÑÐ´Ð¾Ð²Ð°Ð½Ñ Ð·Ð° паÑеÑном `ngOnInit` + `subscribe` + `takeUntil`. ÐÑоÑÐµÑ Ð¿ÐµÑеÑ
Ð¾Ð´Ñ Ð¼Ð¾Ð¶Ð½Ð° виконÑваÑи поÑÑÑпово, ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ Ð·Ð° компоненÑом, без Ð²Ð¿Ð»Ð¸Ð²Ñ Ð½Ð° ÑеÑÑÑ Ð·Ð°ÑÑоÑÑнкÑ. ÐеÑалÑнÑÑе пÑо ÑÑÑаÑегÑÑ Ð¼ÑгÑаÑÑÑ ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½ÑÑв Angular опиÑано Ñ ÑÑаÑÑÑ Ð¿Ñо [мÑгÑаÑÑÑ Ð½Ð° standalone components](/blog/angular/angular-standalone-components-migration-best-practices).
## ÐиÑновок
Resource API в Angular 20 змÑнÑÑ Ð¿ÑдÑ
Ñд до оÑÑÐ¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ
в Angular-заÑÑоÑÑнкаÑ
на ÑÑндаменÑалÑÐ½Ð¾Ð¼Ñ ÑÑвнÑ. ÐлÑÑÐ¾Ð²Ñ Ð²Ð¸Ñновки:
- **resource()** Ñ Ð±Ð°Ð·Ð¾Ð²Ð¸Ð¼ пÑимÑÑивом Ð´Ð»Ñ Ð°ÑинÑ
Ñонного заванÑÐ°Ð¶ÐµÐ½Ð½Ñ ÑеÑез Promise з авÑомаÑиÑним ÑкаÑÑваннÑм запиÑÑв ÑеÑез AbortSignal Ñа ÑеакÑивним вÑдÑÑеженнÑм залежноÑÑей
- **httpResource()** Ð½Ð°Ð´Ð°Ñ Ð²Ð¸ÑокоÑÑÐ²Ð½ÐµÐ²Ñ Ð°Ð±ÑÑÑакÑÑÑ Ð½Ð°Ð´ HttpClient, Ñо ÑÑÑÐ²Ð°Ñ Ñаблонний код Ð´Ð»Ñ GET-опеÑаÑÑй Ñа наÑивно ÑнÑегÑÑÑÑÑÑÑ Ð· ÑнÑеÑÑепÑоÑами й заголовками
- **rxResource()** забезпеÑÑÑ ÑÑмÑÑнÑÑÑÑ Ñз RxJS Ð´Ð»Ñ Ð²Ð¸Ð¿Ð°Ð´ÐºÑв, де поÑÑÑÐ±Ð½Ñ Ð¾Ð¿ÐµÑаÑоÑи на кÑÑÐ°Ð»Ñ debounceTime Ñи retry, викоÑиÑÑовÑÑÑи Observable замÑÑÑÑ Promise
- **ÐалÑдаÑÑÑ ÑеÑез Zod** з опÑÑÑÑ `parse` ÑÑвоÑÑÑ runtime-конÑÑакÑи мÑж ÑÑонÑендом Ñа бекендом, запобÑгаÑÑи ÑендеÑÐ¸Ð½Ð³Ñ Ð½ÐµÐºÐ¾ÑекÑниÑ
даниÑ
- СиÑÑема **ResourceStatus** Ñз ÑÑдковими лÑÑеÑалами (`'idle'`, `'loading'`, `'reloading'`, `'resolved'`, `'error'`, `'local'`) ÑможливлÑÑ Ð´Ð¸ÑеÑенÑÑÐ¹Ð¾Ð²Ð°Ð½Ñ UX-паÑеÑни Ð´Ð»Ñ Ð¿ÐµÑÑого заванÑÐ°Ð¶ÐµÐ½Ð½Ñ Ñа наÑÑÑпниÑ
оновленÑ
- **ÐÑгÑаÑÑÑ** з паÑеÑÐ½Ñ `ngOnInit` + `subscribe` + `takeUntil` виконÑÑÑÑÑÑ Ð¿Ð¾ÑÑÑпово, ÑÑÑÑÑво зменÑÑÑÑи обÑÑг Ñаблонного ÐºÐ¾Ð´Ñ Ñа поÑенÑÑÐ¹Ð½Ñ Ð´Ð¶ÐµÑела виÑокÑв пам'ÑÑÑ
ÐÐ»Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´, ÑÐºÑ Ð³Ð¾ÑÑÑÑÑÑÑ Ð´Ð¾ ÑеÑ
нÑÑниÑ
ÑпÑвбеÑÑд з Angular, впевнене володÑÐ½Ð½Ñ Resource API Ñа ÑÑ Ð¿Ð°ÑеÑнами викоÑиÑÑÐ°Ð½Ð½Ñ ÑÑало Ð±Ð°Ð·Ð¾Ð²Ð¾Ñ Ð²Ð¸Ð¼Ð¾Ð³Ð¾Ñ Ñ 2026 ÑоÑÑ. ÐдаÑнÑÑÑÑ Ð¿Ð¾ÑÑниÑи ÑÑзниÑÑ Ð¼Ñж ÑÑÑома ваÑÑанÑами, меÑ
анÑзм авÑомаÑиÑного ÑкаÑÑÐ²Ð°Ð½Ð½Ñ Ñа ÑнÑегÑаÑÑÑ Ð· валÑдаÑÑÑÑ ÑÑ
ем ÑвÑдÑиÑÑ Ð¿Ñо зÑÑле ÑозÑмÑÐ½Ð½Ñ ÑеакÑÐ¸Ð²Ð½Ð¾Ñ Ð°ÑÑ
ÑÑекÑÑÑи Angular 20.
---
Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack.
HTML version of this page: https://sharpskill.dev/uk/blog/angular/angular-20-resource-api-httpresource-tutorial