Modern Angular uygulamaları genellikle onlarca veya hatta yüzlerce bileşen, hizmet ve modüller içerir. Bu probleme yönelik olarak, uygulamanın farklı kısımları arasında iletişim kurma zorluğudur. Doğrudan ebeveyn-İLETİŞİM:0) / [[Dönetici 1:1) Bağlanan bir uygulama örneği, geliştiriciler tutarlı, çiftleştirilebilir bir çözüm elde edebilir.Bu probleme yönelik tekton modelinin uygulanması, her bileşeni ve hizmetin tek, merkezileştirilmiş bir etkinlik otobüsüni sağlayarak.

Bu makale, bir tekton olayının, RxJS kullanarak Angular'da bir tekton olayı oluşturmasına derin bir at sağlar. Bu model, tekton kalıbının teorik temelini, adım adım adım adım uygulama ayrıntıları, gerçek dünya kullanımı senaryoları ve ileri görüşlüler gibi, tür güvenlik, hafıza yönetimi ve testler inşa edersiniz.

Angular'daki Singleton Desenini Angular

Tekton modeli, yazılım mühendisliğindeki en yaygın kullanılan tasarım modellerinden biridir. temel amacı, bir sınıfın anlık bir nesneyi tam olarak kısıtlamak ve bu nesneye erişim sağlamak. Angular'da, singletons en yaygın olarak kök seviyesinde verilen hizmetler aracılığıyla uygulanır.

Angular Enforces Singletons

Angular'ın bağımlılık enjeksiyonu (DI) sistemi hiyerarşiktir. Bir hizmet Angular'da tektonlar yaratmak için bir hizmet ilan edildiğinde Angular, Angular hizmetin aynı örneğinin tüm uygulama boyunca paylaşıldığı anlamına gelir.

import { Injectable } from '@angular/core';

@Injectable({
 providedIn: 'root'
})
export class MySingletonService {
 // This instance is shared application-wide
}

[[Dind: 5) Sadece tek bir örnek garanti etmez, aynı zamanda ağaç-shaking'i destekler, hizmetin asla enjekte edilmezse, uygulamanın ayak izlerini azaltır.Bu, modüllerdeki desene dayanan eski yaklaşımlar üzerinde önemli bir avantajdır.

Bir Event Bus için Singleton neden?

Bir olay otobüsü aslında bir mesaj merkezidir: herhangi bir bileşeni kendi özel olaylarını ortaya çıkarır ve diğer bileşenler veya hizmetler bu olaylara abone olur.Bu iletişim modeli güvenilir bir şekilde çalışmak için, tüm katılımcılar aynı olay otobüsüne atıfta bulunmalıdır.A singleton bunu garanti eder.Eğer herhangi bir bileşen kendi özel olay otobüsünü yaratırsa, olaylar izole edilir ve iletişim kırılır ve iletişim kırılır.

Uygulama çapında bir Event Bus tasarlayın

Etkinliğimizin temeli RxJS, reaktif programlama için güçlü bir kütüphanedir. Angular'ın kendisi RxJS'ye yoğun olarak güveniyor, bu da olay odaklı hizmetler için doğal bir seçim yapıyor.

Doğru Konu Tipini Seçin

RxJS çeşitli konulardan oluşmaktadır:

  • [FONT:0)Subject[[[Dönetici:0)[[Dönetici:0)[tr|Dönetici[Döneticiler) – Birden çok aboneye değer yayabilecek çok sayıda gözlemlenebilir.
  • [FONT:0)BehaviorSubject[[Dön 1: 1] – Yeni abonelere ilk değer ve tekrar oyun gerektirir.
  • [FONT:0]ReplaySubject[[DÜT:1) – Replays a configuredorable number of previous Emisyon to late abonelerine.
  • [FONT:0]AsyncSubject[[Dönetici: 1 ) – Emits sadece gözlemlenebilir tamamlanmadığında son değeridir.

Klasik bir olay otobüsü için (kullanamayan bir numara) tekrar oynanmayacak, ancak en son etkinlik için abonelere ihtiyacınız varsa, 03.000T:9 1'in göz önünde bulundurulabileceği anlamına gelir, ancak genellikle genel olay otobüsleri gibi uygulama olayları için daha az yaygındır.

Bir Type-Safe Event Bus Oluşturma

Runtime hataları önlemek için, otobüslerin yayabileceği olayları tanımlamanın akıllıca. Olası olay isimlerini ve ilişkili ödeme yük türlerini içeren bir etkinlik haritası arayüzü oluşturabilirsiniz.

export interface AppEvent {
 name: string;
 data: unknown;
}

export interface EventMap {
 'user:login': { userId: string; token: string };
 'user:logout': void;
 'data:updated': { entity: string; id: string };
 'notification:new': { message: string; type: 'success' | 'error' };
}

Haritalanmış tipler kullanarak, o zaman sadece bilinen olayların e-postalmasını ve alt tanımlanmasına izin veren bir tür güvenlik olayı oluşturabilirsiniz.

import { Injectable } from '@angular/core';
import { Subject, Observable } from 'rxjs';
import { filter, map } from 'rxjs/operators';
import { EventMap } from './event-map';

@Injectable({
 providedIn: 'root'
})
export class TypedEventBusService {
 private subject = new Subject<{ name: keyof EventMap; data: EventMap[keyof EventMap] }>();

 emit<K extends keyof EventMap>(eventName: K, data: EventMap[K]): void {
 this.subject.next({ name: eventName, data });
 }

 on<K extends keyof EventMap>(eventName: K): Observable<EventMap[K]> {
 return this.subject.asObservable().pipe(
 filter((event) => event.name === eventName),
 map((event) => event.data as EventMap[K])
 );
 }
}

Bu yaklaşım, der-zaman güvenliği sağlar: yanlış ödeme yükü türü ile bir olay yayamazsınız ve aboneler doğru şekilde veri alır.Bu yaklaşım, yanlış olay yapıları nedeniyle ortaya çıkan zaman hataları olasılığını dramatik şekilde azaltır.

Singleton Event Bus Service'ı Uygulamayın

Teoriyle, pratik, ancak esnek, olay otobüs hizmeti inşa edelim.

Temel Uygulama Temel Uygulama Temel Uygulama Temel Uygulama

Bir jenerik kullanım basit bir servisle başlayın.Bu sürüm, tarif etmek için basit değil.

import { Injectable } from '@angular/core';
import { Subject, Observable } from 'rxjs';
import { filter, map } from 'rxjs/operators';

export interface BusEvent {
 name: string;
 data: any;
}

@Injectable({
 providedIn: 'root'
})
export class EventBusService {
 private bus = new Subject<BusEvent>();

 emit(eventName: string, data?: any): void {
 this.bus.next({ name: eventName, data });
 }

 on(eventName: string): Observable<any> {
 return this.bus.asObservable().pipe(
 filter(event => event.name === eventName),
 map(event => event.data)
 );
 }
}

Tüketicilerin konuyla ilgili olarak aramalarını engellemek için [[Döneticileri” ve “HAKKI 16) operatörlerin kullanımı, abonelerin yalnızca belirli adı eşleştirmelerini sağlar.

Hata İşleme Ekle

Bir üretim uygulamasında, hataları kusursuz bir şekilde işlemek isteyebilirsiniz. Hata bildirimleri de desteklemektedir veya hataların ayrı bir konu ekleyebilirsiniz.

private errorSubject = new Subject<Error>();

emitError(error: Error): void {
 this.errorSubject.next(error);
}

Basitlik için, temel olayı otobüsleri sadece olaylara odaklandık, ancak bunu gerekli olarak genişletebilirsiniz.

Abonelik Yönetimi

Gözlemlenebilir aboneliklerle en yaygın hatalardan biri iptal etmeyi unutur.Eğer bir bileşen aboneleri olay otobüsüne aboneyse, abonelik aktif kalır ve hafıza sızıntılarına veya istenmeyen yan etkilere neden olabilir.Her zaman abonelikleri saklar ve temizleyebilir.)

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
import { EventBusService } from './event-bus.service';

@Component({
 selector: 'app-example',
 template: `<div>Listening for events...</div>`
})
export class ExampleComponent implements OnInit, OnDestroy {
 private subscription: Subscription;

 constructor(private eventBus: EventBusService) {}

 ngOnInit(): void {
 this.subscription = this.eventBus.on('data:updated').subscribe(data => {
 console.log('Data updated:', data);
 });
 }

 ngOnDestroy(): void {
 if (this.subscription) {
 this.subscription.unsubscribe();
 }
 }
}

Ayrıca, bir bileşen tahrip edildiğinde otomatik olarak abonelikleri iptal etmek için [[Şerefli|seçmiş) kalıbı kullanabilirsiniz.

Event Bus'ı Bileşenlerinde Kullanın

Şimdi sağlam bir olay otobüsüne sahip olduğumuza göre, gerçekçi bir çapraz-komponent iletişim senaryosu ile harekete geçelim.

Örnek: Bildirim Sistemi

Bir başlık parçası ile bir uygulama düşünün (ki bildirimler gösterilir) ve kullanıcının bir bildirim tetikleyebildiği bir ayarlar. Bu bileşenler bileşen bileşeni ağacında ilgili değildir, bu yüzden geleneksel olarak 444D:23). olaylar bunu kolayca çözemez.

[FONT=0)[değiştir | kaynağı değiştir]

import { Component } from '@angular/core';
import { EventBusService } from '../services/event-bus.service';

@Component({
 selector: 'app-notification-publisher',
 template: `
 <button (click)="sendNotification()">
 Trigger Notification
 </button>
 `
})
export class NotificationPublisherComponent {
 constructor(private eventBus: EventBusService) {}

 sendNotification(): void {
 this.eventBus.emit('notification:new', {
 message: 'Your settings have been saved.',
 type: 'success'
 });
 }
}

[0][değiştir | kaynağı değiştir]

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
import { EventBusService } from '../services/event-bus.service';

@Component({
 selector: 'app-notification-display',
 template: `
 <div *ngIf="lastNotification" class="notification" [ngClass]="lastNotification.type">
 {{ lastNotification.message }}
 </div>
 `
})
export class NotificationDisplayComponent implements OnInit, OnDestroy {
 lastNotification: { message: string; type: string } | null = null;
 private subscription: Subscription;

 constructor(private eventBus: EventBusService) {}

 ngOnInit(): void {
 this.subscription = this.eventBus.on('notification:new').subscribe(data => {
 this.lastNotification = data;
 });
 }

 ngOnDestroy(): void {
 if (this.subscription) {
 this.subscription.unsubscribe();
 }
 }
}

Bu kurulumda, iki bileşen asla birbirlerini ithal etmezler. Sadece paylaşılanIZLIĞI:26'ye bağlılar.Bu gevşek darbe, kodu korumak, test etmek ve yeniden faktörlemeyi kolaylaştırır.

Etkinlik Bus'ı Hizmetlerde Kullanımı

Hizmetler ayrıca olaylara abone olabilir ve buna göre tepki verebilir. Örneğin, bir kimlik doğrulama hizmeti, önbellekli jetonları açıklayabilecek bir olay için dinlenebilir.

import { Injectable, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
import { EventBusService } from './event-bus.service';

@Injectable({ providedIn: 'root' })
export class AuthService implements OnDestroy {
 private subscription: Subscription;

 constructor(private eventBus: EventBusService) {
 this.subscription = this.eventBus.on('user:logout').subscribe(() => {
 this.clearSession();
 });
 }

 clearSession(): void {
 // Clear tokens, navigate to login, etc.
 }

 ngOnDestroy(): void {
 this.subscription?.unsubscribe();
 }
}

Not that even the service is a singleton, it still implementsENFLT:29) Uygulama kapatıldığında abonelikleri temizlemek için (örneğin, Angular Universal SSR veya test sırasında).

Gelişmiş Tahminler

Tekton bir olay otobüsü güçlü olsa da, her geliştiricinin anlaması gereken bazı gelişmiş konulardır.

Performans ve Debouncing

Eğer olaylar yüksek bir frekansta kovulursa (örneğin, fare hareketi veya gerçek zamanlı veri akışı sırasında), abone bileşenlerdeki operatörler tarafından kullanılan [[FONTD:30) veya [[FONTT:31) kullanımı göz önünde bulundurulabilir. Ancak, bu tür operatörlerin abonelik seviyesinde uygulanması gerektiğinin farkında olun, olay otobüsünde değil, farklı aboneler farklı oran-limiting ihtiyaçları olabilir.

Memory Leaks

Daha önce alıntının önemini vurguladık, ancak tekrarlıyor. Olay gözlemlenebilirlik sonsuzdur: konu sınırsız bir şekilde ya da uygulama yok olana kadar asla tam olarak tam anlamıyla tam olarak tam anlamıyla tamamlanmış değildir. Kayıtsızca unutulmuş herhangi bir bileşen, büyük uygulamalarda bir bellek sızıntısına neden olabilir.

private destroy$ = new Subject<void>();

ngOnInit(): void {
 this.eventBus.on('data:updated')
 .pipe(takeUntil(this.destroy$))
 .subscribe(data => { ... });
}

ngOnDestroy(): void {
 this.destroy$.next();
 this.destroy$.complete();
}

Debugging ve Logging

Olay odaklı sistemler zor olabilir çünkü olayların akışı hemen görünür değildir. Olay otobüsünün kendi başına kayıt olabilirsiniz. Örneğin, gelişim modunda yayılan her olayı oturum açabilirsiniz:

emit(eventName: string, data?: any): void {
 if (environment.production === false) {
 console.debug(`[EventBus] Emitting: "${eventName}"`, data);
 }
 this.bus.next({ name: eventName, data });
}

Bu basit ek, zaman zamanınızı kurtarabilir.

Etkinlik Bus'ı Test Etmek

Olay otobüsünün kendisini basit bir şekilde test edin: Bir etkinliğe abone olabilirsiniz, yayabilirsiniz ve abonenin doğru verileri aldığını kontrol edebilirsiniz.

import { TestBed } from '@angular/core/testing';
import { EventBusService } from './event-bus.service';

describe('EventBusService', () => {
 let service: EventBusService;

 beforeEach(() => {
 TestBed.configureTestingModule({});
 service = TestBed.inject(EventBusService);
 });

 it('should emit and receive events', (done) => {
 const testData = { foo: 'bar' };
 service.on('test:event').subscribe(data => {
 expect(data).toEqual(testData);
 done();
 });
 service.emit('test:event', testData);
 });

 it('should not deliver events to subscribers of different names', () => {
 const spy = jasmine.createSpy();
 service.on('other:event').subscribe(spy);
 service.emit('test:event', {});
 expect(spy).not.toHaveBeenCalled();
 });
});

Olay otobüsü kullanan bileşenleri test ederken, bir casusu enjekte etmek veya alaycı bir şekilde enjekte etmek, bileşeni doğru olayları yaydığını veya doğru olayları doğru şekilde yanıtlayanları doğrulamak için.

Faydaları ve Potansiyel Pitfalls

Faydaları Faydaları Faydaları

  • [FONT:0)Decoupled İletişim) - Bileşenler ve hizmetler birbirine doğrudan referans olmadan etkileşime girebilir, kodbase daha modüler hale getirebilir.
  • [FONT:0) Tek Gerçek Kaynağı[[Dönetici:0) – Tekton olayı otobüsü, tüm olayların tek bir kanal aracılığıyla akışa, traksiyonu ve debuggingleri basitleştirmesini sağlar.
  • [FONT=0)Redük Memory Footprint[[[Döntilmiş: 1)) – Birden çok ayrı olay yayıcı oluşturmak yerine, özellikle büyük uygulamalarda faydalı olan bir örneke sahipsiniz.
  • [FONT:0) Doğa tarafından aktif olarak [Dönetici: 1) – RxJS'den faydalanarak güçlü operatörleri (dövme, Latest vs.) karmaşık olay akışlarını işlemek için.
  • [FONT:0]Testable[DÜT:1) - Çünkü olay otobüsü enjektif bir hizmettir, kolayca ünite testlerinde alay edebilirsiniz.

Potansiyel Pitfalls

  • [FONT:0)Overuse[[DÜDÜT:1) - Her iletişim parçası için küresel bir olay otobüsüne dayanarak, verileri takip etmek için daha zor hale getirebilir, “spaghetti olayları” için öncelikle çapraz kesme endişeleri için kullanın (birleştirmeler, auth durum, küresel ayarlar) rutin ebeveyn-çocuk iletişimi için daha zor hale getirebilir.
  • [FONT:0) Explicit Typing olmadan Tip Güvenliği) – Eğer tip bir yaklaşımı atsanız, der zaman güvenliğini kaybedersiniz ve zaman kaybı riskini artırırsınız.
  • [FONT:0]Memory Leaks[[Dönetici: 1 ) – Tartışmalı olarak, giriş yapmayı unutanların #1 kaynağıdır.
  • [FONT:0]Difficulty in Tracing Event Flow) – Doğrudan bir yöntem çağrısının aksine, bir olayın kaynağı, yalnızca olay otobüsünden açık değildir. İyi adlandırma kongrelerinden ve tutarlı bir giriş bunu azaltır.
  • [FONT:0)Cascading Events[Dönetici: 1)[Döneticileri tetikleyen olaylar, dikkatli tasarlanmamışsa sonsuz döngüler yaratabilir.

Singleton Event Bus'a Alternatifler

Tekton olayı otobüs güçlü bir araçtır, Angular'daki çapraz sorumlu iletişimi yönetmek için tek yol değildir.Bu alternatifleri düşünün:

  • [FONT:0)State Management Library (NgRx, Akita, NGXS)) – Bunlar uygulama durumunu yönetmek için yapılandırılmış, Redux benzeri bir model sağlar. Küçük projeler için aşırı derecede, karmaşık uygulamalar için mükemmel.
  • [FONT:0) Davranışla Hizmet Alınmış ([Dönder: 1) – Temel bir olay otobüsü yerine, belirli durumu gözlemlenebilir olarak ortaya koyan özel hizmetler oluşturabilirsiniz. Bu daha tür güvenli ve “düşük batı” anlamına gelir.
  • [FONT:0)Component-Level İletişim[Dönetici: 1) - Yakın ilişkili bileşenler için, [[Ücretsiz KAYNAKLAR: 0,9|Dönetici bileşeni veya paylaşılan bir ebeveyn bileşeni genellikle daha basit ve daha şeffaf.
  • [FONT:0] Soru paramları veya devletle ilgili olarak ) - Bazı sorumlu iletişim rota verileri aracılığıyla elde edilebilir.

Tekton olayı tam bir devlet yönetimi kütüphanesi olmadan gevşek darbeye ihtiyacınız olduğunda parlar. hafif, uygulamak ve esnektir - ancak disiplin talep eder.

Sonuç Sonuç Sonuç Sonuç Sonuç Sonuç Sonuç Sonuç

Angular'ın bağımlılık enjeksiyon sistemi ve RxJS'in güçlü gözlemleyici akışları için tekton bir deseni uygulamak, uygulamanızı daha güvenli ve ölçeklenebilir hale getiren merkezi bir etkinlik merkezi oluşturabilirsiniz.

Tektonların arkasındaki teoriyi kaptık, hem temel hem de tip uygulamalarla sağlam bir olay otobüsü inşa ederek yürüdük, etkinlik emisyonu için her zaman sorumsuz kullanım gösterdi ve güvenlik için etkinliklerinizi yazıp ele alalım.

Tekton olayının anlam verdiği bir modelini kabul edin, ancak Angular ile bir araya gelmekten kaçınır[Dönetici, reaktif formlar ve akıllı /dumb bileşeni ayrılıklar –[Dönetici, daha profesyonel Angular uygulamaları inşa etmenize yardımcı olacaktır.)