Сервіси та впровадження залежностей в Angular
Що таке Сервіси?
Сервіс — це клас, який інкапсулює перезавантажувану логіку — отримання даних, бізнес-правила, ведення журналу тощо. Сервіси спільно використовуються між компонентами через систему Впровадження Залежностей (DI) Angular.
Створення Сервісу
typescript
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root' // Доступний на рівні додатку (одиночний екземпляр)
})
export class UserService {
private apiUrl = '/api/users';
constructor(private http: HttpClient) {}
getUsers(): Observable<User[]> {
return this.http.get<User[]>(this.apiUrl);
}
getUserById(id: string): Observable<User> {
return this.http.get<User>(\`\${this.apiUrl}/\${id}\`);
}
createUser(user: Partial<User>): Observable<User> {
return this.http.post<User>(this.apiUrl, user);
}
}Впровадження Сервісу
typescript
@Component({
selector: 'app-user-list',
template: \`
<ul>
<li *ngFor="let user of users">{{ user.name }}</li>
</ul>
\`
})
export class UserListComponent implements OnInit {
users: User[] = [];
// Впровадження сервісу через конструктор
constructor(private userService: UserService) {}
ngOnInit() {
this.userService.getUsers().subscribe(users => {
this.users = users;
});
}
}Сучасна функція inject()
typescript
import { inject } from '@angular/core';
@Component({ /* ... */ })
export class UserListComponent {
private userService = inject(UserService);
// Конструктор не потрібен!
}Надання Сервісів
typescript
// 1. На рівні кореня (одиночний екземпляр — найпоширеніший)
@Injectable({ providedIn: 'root' })
export class AuthService {}
// 2. На рівні компонента (новий екземпляр для кожного компонента)
@Component({
providers: [LoggerService] // Кожен компонент отримує свій власний екземпляр
})
export class MyComponent {}
// 3. На рівні модуля
@NgModule({
providers: [AnalyticsService]
})
export class AnalyticsModule {}Токени Впровадження
Для залежностей, що не є класами:
typescript
import { InjectionToken } from '@angular/core';
export const API_URL = new InjectionToken<string>('API_URL');
// Надання
@NgModule({
providers: [
{ provide: API_URL, useValue: 'https://api.example.com' }
]
})
// Впровадження
constructor(@Inject(API_URL) private apiUrl: string) {}
// або
private apiUrl = inject(API_URL);Типи Провайдерів
| Провайдер | Опис | Приклад |
|---|---|---|
useClass | Надати інший клас | { provide: Logger, useClass: FileLogger } |
useValue | Надати статичне значення | { provide: API_URL, useValue: 'https://...' } |
useFactory | Надати через фабричну функцію | { provide: Service, useFactory: () => new Service() } |
useExisting | Псевдонім для існуючого провайдера | { provide: OldService, useExisting: NewService } |
Важливо:
Сервіси інкапсулюють перезавантажувану логіку і спільно використовуються через Впровадження Залежностей. Використовуйте @Injectable({ providedIn: 'root' }) для одиночних екземплярів на рівні додатку. Використовуйте сучасну функцію inject() замість впровадження через конструктор, коли це можливо. DI робить код тестованим (мок-сервіси в тестах) і модульним (заміна реалізацій).
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.