Servisler, Angular uygulamanız genelinde paylaşabileceğiniz yeniden kullanılabilir kod parçalarıdır. Bunları genellikle veri getirme, iş mantığı veya birden fazla bileşenin erişmesi gereken diğer işlevleri yönetmek için kullanırsınız.
Bir service oluşturma
Angular CLI kullanarak aşağıdaki komutla bir servis oluşturabilirsiniz:
ng generate service CUSTOM_NAME
Bu komut, src dizininizde özel bir CUSTOM_NAME.ts dosyası oluşturur.
Ayrıca bir TypeScript sınıfına @Service() dekoratörünü ekleyerek manuel olarak bir servis oluşturabilirsiniz. Bu, Angular'a sınıfı enjekte edilebilir bir bağımlılık olarak kullanabileceğinizi söyler.
Aşağıdaki örnek, kullanıcıların veri eklemesine ve veri almasına olanak tanıyan bir servis tanımlar:
src/app/basic-data-store.ts
import {Service} from '@angular/core';
@Service()
export class BasicDataStore {
private data: string[] = [];
addData(item: string): void {
this.data.push(item);
}
getData(): string[] {
return [...this.data];
}
}
Service'ler nasıl kullanılabilir hale gelir
Service'ler varsayılan olarak kök seviyede sağlanır. Bir service global olarak sağlandığında Angular üç temel avantajı garanti eder:
- Tek örnek (singleton): Tüm uygulama için tek ve paylaşılan bir örnek oluşturur.
- Global erişilebilirlik: Manuel provider kaydı olmadan her yerden otomatik olarak erişilebilir.
- Tree-shake edilebilirlik: Kodunuz service'i hiçbir zaman açıkça kullanmıyorsa, service'in nihai üretim paketinin dışında kalmasını sağlar.
@Service ve @Injectable dekoratörlerini kullanma
@Service dekoratörü, geleneksel @Injectable({ providedIn: 'root' }) sözdiziminin modern ve ergonomik bir kısayoludur.
Hangi dekoratörün sizin durumunuza uyduğuna karar vermek için bu hızlı başvuruyu kullanın:
| Özellik / Gereksinim | @Service |
@Injectable |
|---|---|---|
inject() fonksiyonu desteği |
Evet | Evet |
| Constructor tabanlı DI | ❌ Hayır | Evet |
| Örtük kök singleton provider | Evet | ❌ Hayır ({providedIn: 'root'} gerekir) |
Gelişmiş provider anahtarları (useClass, vb.) |
❌ Hayır | Evet |
| Özel başlatma factory'leri | Evet | Evet |
Kök dışı kapsamlar (platform, vb.) |
❌ Hayır | Evet |
Uygulamayı bir factory ile değiştirme
Singleton'ın nasıl oluşturulduğunu kontrol etmeniz gerekiyorsa, örneğin ortama bağlı olarak farklı bir uygulamayı devreye almak için, bir factory fonksiyonu geçirin.
Factory bir enjeksiyon bağlamında çalışır, böylece diğer bağımlılıkları okumak için içinde inject() kullanabilirsiniz.
Aşağıdaki Analytics servisi yerelde bir no-op'tur, böylece olaylar geliştirme sırasında konsolu kirletmez. Üretimde factory bir ANALYTICS_ENABLED token'ını okur ve olayları gerçek izleyiciye ileten bir GoogleAnalytics alt sınıfı döndürür:
src/app/analytics.ts
import {inject, InjectionToken, Service} from '@angular/core';
import {ANALYTICS_ENABLED} from './token';
@Service({
factory: () => (inject(ANALYTICS_ENABLED) ? new GoogleAnalytics() : new Analytics()),
})
export class Analytics {
track(event: string, payload?: Record<string, unknown>) {
// Varsayılan olarak no-op.
}
}
class GoogleAnalytics extends Analytics {
override track(event: string, payload?: Record<string, unknown>) {
// Google Analytics'e bir analitik olayı gönderir
}
}
NOTE: factory seçeneği, @Injectable'ın useClass, useValue, useExisting ve useFactory seçeneklerinin yerini alır. Bunlardan herhangi birine ihtiyacınız varsa @Injectable kullanmaya devam edin.
Otomatik sağlamadan vazgeçme
Varsayılan olarak @Service, sınıfı kök enjektörde sağlar. Onu manuel olarak sağlamak isterseniz, örneğin belirli bir route'a veya bileşene kapsamlamak için, autoProvided: false olarak ayarlayın:
src/app/analytics-logger.ts
import {Service} from '@angular/core';
@Service({autoProvided: false})
export class AnalyticsLogger {
trackEvent(name: string) {
console.log('event:', name);
}
}
Bu durumda, tıpkı düz bir @Injectable() ile olduğu gibi, servisi bir providers dizisine eklemekten siz sorumlu olursunuz:
@Service mi @Injectable mı kullanmalı
inject() fonksiyonunu bağımlılıkları için kullanan yeni bir singleton sınıfı oluşturuyorsanız @Service'e başvurun. Aşağıdakilerden herhangi birine ihtiyacınız olduğunda @Injectable kullanmaya devam edin:
- Constructor tabanlı bağımlılık enjeksiyonu.
@Serviceyalnızcainject()fonksiyonunu destekler. - Gelişmiş sağlayıcı yapılandırması örneğin
useClass,useValue,useExistingveyauseFactory.@Servicebunun yerine tek birfactoryseçeneği sunar. - Kök dışı kapsamlar örneğin
providedIn: 'platform'.
Bir service'i enjekte etme
providedIn: 'root' ile bir servis oluşturduktan sonra, @angular/core'dan inject() fonksiyonunu kullanarak uygulamanızın herhangi bir yerinde enjekte edebilirsiniz.
Bir bileşene enjekte etme
import {Component, inject} from '@angular/core';
import {BasicDataStore} from './basic-data-store';
@Component({
selector: 'app-example',
template: `
<div>
<p>{{ dataStore.getData() }}</p>
<button (click)="dataStore.addData('More data')">Add more data</button>
</div>
`,
})
export class Example {
dataStore = inject(BasicDataStore);
}
Başka bir service'e enjekte etme
import {inject, Service} from '@angular/core';
import {AdvancedDataStore} from './advanced-data-store';
@Service()
export class BasicDataStore {
private advancedDataStore = inject(AdvancedDataStore);
private data: string[] = [];
addData(item: string): void {
this.data.push(item);
}
getData(): string[] {
return [...this.data, ...this.advancedDataStore.getData()];
}
}
Sonraki adımlar
providedIn: 'root' çoğu kullanım durumunu karşılarken, Angular ayrıca daha özel senaryolar için servisleri yapılandırabileceğiniz ek yollar da sunar:
- Bileşene özgü örnekler - Bileşenlerin kendi izole servis örneklerine ihtiyaç duyması durumunda
- Manuel yapılandırma - Çalışma zamanı yapılandırması gerektiren servisler için
- Fabrika sağlayıcıları - Çalışma zamanı koşullarına göre dinamik servis oluşturma için
- Değer sağlayıcıları - Yapılandırma nesneleri veya sabitler sağlamak için
Bu gelişmiş desenler hakkında daha fazla bilgiyi sonraki kılavuzda bulabilirsiniz: bağımlılık sağlayıcılarını tanımlama.