کلاینت HTTP (HTTP Client)
«کلاینت HTTP انگولار» راهِ حرف زدن با سرور است. «HTTP» یک زبان درخواست /پاسخ است. بنابراین با آن داده می گیریم یا می فرستیم. همچنین رابط را هنگام بارگیری و خطا، واضح نگه داریم.
مبانی HTTP در انگولار
«Observable» جریانِ داده زمان دار است. با subscribe() یا پایپ async آن را مصرف کن. سپس یک بار در بوت استرپ از provideHttpClient() استفاده کن تا کلاینت فعال شود.
import { provideHttpClient, HttpClient } from '@angular/common/http';
// bootstrapApplication(App, { providers: [provideHttpClient()] });
// inside a component
// http.get<User[]>('/api/users').subscribe({
// next: (d) => { users = d; };
// });
نکته: آدرس پایه API را متمرکز نگه دار. سپس در سرویس ها استفاده کن.
دریافت داده با GET
با http.get<T>() بخوان. سپس فلگ های loading و error را کنترل کن. مانند رفرش نمرات مدرسه، اما با دکمه «Load».
import { bootstrapApplication } from '@angular/platform-browser';
import { Component, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { provideHttpClient, HttpClient } from '@angular/common/http';
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule],
template: `
<h3>HttpClient</h3>
<button (click)="load()">Load Users</button>
<p *ngIf="loading">Loading...</p>
<p *ngIf="error" style="color:crimson">{{ error }}</p>
<ul>
<li *ngFor="let u of users">{{ u.name }} ({{ u.email }})</li>
</ul>
`
})
export class App {
http = inject(HttpClient);
users: any[] = [];
loading = false;
error = '';
load() {
this.loading = true;
this.error = '';
this.http.get<any[]>('https://jsonplaceholder.typicode.com/users')
.subscribe({
next: (data) => { this.users = data; this.loading = false; };
error: () => { this.error = 'Failed to load users'; this.loading = false; };
});
}
}
bootstrapApplication(App, { providers: [provideHttpClient()] });
ارسال داده با POST
با http.post<T>() بساز. سپس هنگام ارسال، دکمه را غیرفعال کن. مانند فرستادن فرم ثبت نام مدرسه.
import { bootstrapApplication } from '@angular/platform-browser';
import { Component, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { provideHttpClient, HttpClient } from '@angular/common/http';
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule],
template: `
<h3>HttpClient POST</h3>
<button (click)="createPost()" [disabled]="loading">Create Post</button>
<p *ngIf="loading">Sending...</p>
<p *ngIf="error" style="color:crimson">{{ error }}</p>
<div *ngIf="result">
<p>Created Post ID: {{ result.id }}</p>
<p>Title: {{ result.title }}</p>
</div>
`
})
export class App {
http = inject(HttpClient);
loading = false;
error = '';
result: any = null;
createPost() {
this.loading = true;
this.error = '';
this.result = null;
this.http.post<any>('https://jsonplaceholder.typicode.com/posts', {
title: 'foo',
body: 'bar',
userId: 1
}).subscribe({
next: (res) => { this.result = res; this.loading = false; };
error: () => { this.error = 'Failed to create post'; this.loading = false; };
});
}
}
bootstrapApplication(App, { providers: [provideHttpClient()] });
مدیریت خطا و تلاش مجدد
پیام خطا را شفاف نشان بده. سپس امکان «Retry» بده. خطاهای 5xx شاید موقتی باشند؛ 4xx معمولاً مشکل درخواست است.
import { bootstrapApplication } from '@angular/platform-browser';
import { Component, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { provideHttpClient, HttpClient, withInterceptors, HttpResponse, HttpErrorResponse, HttpRequest, HttpHandlerFn } from '@angular/common/http';
import { of, throwError } from 'rxjs';
function mockHttp(req: HttpRequest<any>, next: HttpHandlerFn) {
if (req.method === 'GET' && req.url.includes('jsonplaceholder.typicode.com/usersx')) {
return throwError(() => new HttpErrorResponse({ status: 404, statusText: 'Not Found', url: req.url }));
}
if (req.method === 'GET' && req.url.includes('jsonplaceholder.typicode.com/users')) {
const body = [
{ id: 1, name: 'Leanne Graham', email: 'leanne@example.com' },
{ id: 2, name: 'Ervin Howell', email: 'ervin@example.com' }
];
return of(new HttpResponse({ status: 200, body }));
}
return next(req);
}
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule],
styles: [`
button { margin-right: 8px; }
.error { color: crimson; }
.ok { color: seagreen; }
`],
template: `
<h3>HTTP Error Handling</h3>
<div>
<button (click)="loadOk()" [disabled]="loading">Load OK</button>
<button (click)="loadFail()" [disabled]="loading">Load Fail</button>
<button (click)="retry()" [disabled]="!lastAction || loading">Retry</button>
</div>
<p *ngIf="loading">Loading...</p>
<p *ngIf="error" class="error">{{ error }}</p>
<p *ngIf="!error && data" class="ok">Loaded {{ isArray(data) ? data.length + ' items' : '1 item' }}</p>
<ul *ngIf="isArray(data)">
<li *ngFor="let u of data">{{ u.name }} ({{ u.email }})</li>
</ul>
`
})
export class App {
http = inject(HttpClient);
loading = false;
error = '';
data: any[] | null = null;
lastAction = '';
isArray(value: unknown): value is any[] { return Array.isArray(value as any); }
fetch(url: string): void {
this.loading = true;
this.error = '';
this.data = null;
this.http.get<any[]>(url).subscribe({
next: (res) => { this.data = res; this.loading = false; };
error: (err) => {
const status = err?.status ?? 'unknown';
this.error = `Request failed (status ${status}). Please try again.`;
this.loading = false;
};
});
}
loadOk() {
this.lastAction = 'ok';
this.fetch('https://jsonplaceholder.typicode.com/users');
}
loadFail() {
this.lastAction = 'fail';
this.fetch('https://jsonplaceholder.typicode.com/usersx');
}
retry() {
if (this.lastAction === 'ok') {
this.loadOk();
}
else if (this.lastAction === 'fail') {
this.loadFail();
}
}
}
bootstrapApplication(App, { providers: [provideHttpClient(withInterceptors([mockHttp]))] });
اینترسپتور (Interceptor) برای هر درخواست
«اینترسپتور» فیلترِ سراسری درخواست/پاسخ است. بنابراین هدرِ احراز هویت، لاگ و Retry اینجا قرار می گیرد. یک بار در بوت استرپ ثبت کن.
import { HttpInterceptorFn, provideHttpClient, withInterceptors } from '@angular/common/http';
export const authInterceptor: HttpInterceptorFn = (req, next) => {
const cloned = req.clone({ setHeaders: { Authorization: 'Bearer TOKEN' } });
return next(cloned);
};
bootstrapApplication(App, {
providers: [provideHttpClient(withInterceptors([authInterceptor]))]
});
هشدار: ورودیِ کاربر را مستقیم داخل URL نگذار. سپس بخش های متغیر را اعتبارسنجی کن.
گام های عملی سریع
- در بوت استرپ از
provideHttpClient()استفاده کن. - در کامپوننت یا سرویس،
inject(HttpClient)را صدا بزن. - فلگ های loading و error را مدیریت کن.
جمع بندی سریع
- GET می خوانَد؛ POST می سازد.
- Observable را با
subscribe()مصرف کن. - UI را با loading/error شفاف نگه دار.
- اینترسپتور جای منطقِ مشترک است.
برای عمق بیشتر به سرویس ها و DI و روتر سر بزن. همچنین لینک سریعِ همین صفحه: کلاینت HTTP انگولار.