EventEmitter'ın doğru kullanımı nedir?


225

Kullanıcının hizmetinde EventEmitter kullandığı CustomHttp içindeki Access EventEmitter Hizmeti gibi soruları okudum , ancak bu yorumda kullanmaması ve bunun yerine Observables'ı doğrudan hizmetlerinde kullanması önerildi .

Çözümün EventEmitter'ı çocuğa geçirmesini ve abone olmasını önerdiği bu soruyu da okudum .

O zaman sorum şu: Bir EventEmitter'a manuel olarak abone olmamalı mıyım yoksa abone olmamam mı gerekiyor? Nasıl Kullanmalıyım?



2
Mark'ın her zamanki gibi iyi cevabı, ama aslında neden açıkladığımı açıklamıyor. Kapatmaya karşı değilim, ama önce fikrini istiyorum. @MarkRajcok düşünceler?
Eric Martinez

Bunu açık tutmak istiyorum (ve eminim ki burada insanları işaret edeceğim - diğer cevabımı burada işaret edecek şekilde düzenledim!). Cevabınızda ek bilgiler var. Ama iki soru başlığı istiyorum ... diğeri "EventEmitter'ın doğru kullanımı nedir?"
Mark Rajcok

@MarkRajcok bu başlığı beğendim ama mevcut cevaba uymuyor, bu yüzden daha sonra güncellemeyi, nasıl kullanılacağını ve nasıl kullanılacağına dair örnekler ekleyeceğim. Geri bildiriminiz için teşekkür ederiz :)
Eric Martinez

@MarkRajcok önerildiği gibi düzenlenmiştir (y), (önerilen başlığı kopyalayıp yapıştırın, tüm krediler size).
Eric Martinez

Yanıtlar:


342

TL; DR :

Hayır, onlara manuel olarak abone olmayın, hizmetlerde kullanmayın. Bunları yalnızca bileşenlerde olay yaymak için belgelerde gösterildiği gibi kullanın. Açısal soyutlamayı yenmeyin.

Cevap:

Hayır, manuel olarak abone olmamalısınız.

EventEmitter bir açısal2 soyutlamasıdır ve tek amacı bileşenlerdeki olayları yaymaktır. Rob Wormald'dan bir yorum alıntılama

[...] EventEmitter gerçekten Açısal bir soyutlamadır ve yalnızca bileşenlerde özel Olaylar yayınlamak için hemen hemen kullanılmalıdır. Aksi takdirde, Rx'i başka bir kütüphane gibi kullanın.

Bu olay EventEmitter'in belgelerinde çok açık bir şekilde ifade edilmiştir.

Özel Etkinlikler düzenlemek için yönergeler ve bileşenler tarafından kullanın.

Kullanmayla ilgili sorun nedir?

Angular2, EventEmitter'in Gözlemlenebilir olmaya devam edeceğini asla garanti etmeyecektir. Yani bu, kodumuzun değişmesi durumunda yeniden düzenlenmesi anlamına gelir. Erişmemiz gereken tek API emit()yöntemi. Bir EventEmitter'a asla manuel olarak abone olmamalıyız.

Yukarıda belirtilenlerin hepsi bu Ward Bell'in yorumunda daha açıktır (makaleyi ve bu yorumun cevabını okumanız önerilir ). Referans için alıntı

Gözlemlenebilir olmaya devam eden EventEmitter'a güvenmeyin!

İleride orada olan Gözlemlenebilir operatörlere güvenmeyin!

Bunlar yakında kullanımdan kaldırılacak ve muhtemelen yayınlanmadan önce kaldırılacak.

EventEmitter öğesini yalnızca bir alt öğe ve üst bileşen arasındaki olay bağlama için kullanın. Abone olmayın. Bu yöntemlerden hiçbirini çağırma. Sadece araeve.emit()

Onun yorumu, Rob'un uzun zaman önce yaptığı yorumla aynı doğrultuda.

Peki, nasıl düzgün kullanılır?

Bileşeninizden etkinlik yayınlamak için kullanın. Aşağıdaki örneğe bir göz atın.

@Component({
    selector : 'child',
    template : `
        <button (click)="sendNotification()">Notify my parent!</button>
    `
})
class Child {
    @Output() notifyParent: EventEmitter<any> = new EventEmitter();
    sendNotification() {
        this.notifyParent.emit('Some value to send to the parent');
    }
}

@Component({
    selector : 'parent',
    template : `
        <child (notifyParent)="getNotification($event)"></child>
    `
})
class Parent {
    getNotification(evt) {
        // Do something with the notification (evt) sent by the child!
    }
}

Nasıl kullanılmaz?

class MyService {
    @Output() myServiceEvent : EventEmitter<any> = new EventEmitter();
}

Orada dur ... zaten yanılıyorsun ...

Umarım bu iki basit örnek EventEmitter'ın uygun kullanımını açıklığa kavuşturacaktır.


1
directives : [Child]Bileşen tanımında ne ile kastediyorsunuz ? Bu derlenmiş gibi görünmüyor ve Angular2 belgelerinde açıklanan bulamıyorum.
themathmagician

1
@Eric: Örneğinizde nasıl kullanılmaması çok açık, neden bir hizmette '@Output' dekoratörüne ihtiyacımız var?
trungk18

1
@themathmagician biraz araştırma sonrasında buldum burada o directiveskelime beri kaldırılmıştır. Kullanım declarationsanahtar kelimeyi @NgModuleyönlendirildiği gibi burada ya burada
cjsimon

5
Toby'nin daha yeni cevabı hakkında yorumunuz var mı? Sanırım cevabı bugünlerde kabul edilmiş olmalı.
Arjan

7
@Eric Bu cevabı yazdığınızda, Ward Bell'den alıntı yaparak, 'Bunlar yakında kaldırılacak ve muhtemelen yayınlanmadan önce kaldırılacak' yazdınız. Ama bu 2 yıl önce ifade edildi ve şimdi açısal var6. Bu ifade halen geçerli mi? Resmi dokümanda EventEmitter'in hâlâ abone () yöntemine sahip olduğunu görmeye devam ediyorum, bu yüzden Google, EE'yi Rxjs konularına dayandırmayı bırakmak istiyorsa zaten yapacaklarını düşünüyorum. Peki orijinal cevabınızın hala Angular'ın mevcut durumuna uygun olduğunu düşünüyor musunuz?
Nad G

101

Evet, devam et ve kullan.

EventEmitterBir olan kamu, belgelenmiş tip nihai Açısal Çekirdek API. Dayalı Observableolup olmadığı önemsizdir; belgelenmiş emitve subscribeyöntemleri ihtiyacınız olana uygunsa, devam edin ve kullanın.

Dokümanlarda da belirtildiği gibi:

Rx.Observable kullanır, ancak burada belirtildiği gibi çalışması için bir adaptör sağlar: https://github.com/jhusain/observable-spec

Spesifikasyonun referans uygulaması mevcut olduğunda, ona geçin.

Böylece Observablebelli bir şekilde davranan benzer bir nesne istiyorlardı , uyguladılar ve halka açık hale getirdiler. Kullanılmaması gereken sadece içsel bir Açısal soyutlama olsaydı, bunu herkese açık yapmazdı.

Belirli bir türdeki olayları gönderen bir yayıcıya sahip olmanın yararlı olduğu birçok zaman vardır. Bu sizin kullanım durumunuzsa, devam edin. Bağlantı kurdukları spesifikasyonun bir referans uygulaması mevcutsa / mevcutsa, tıpkı diğer poli dolgularda olduğu gibi bir bırakma yedeği olmalıdır.

Sadece subscribe()işleve ilettiğiniz jeneratörün bağlı spesifikasyona uyduğundan emin olun . Döndürülen nesnenin, unsubscribejeneratöre herhangi bir referansı serbest bırakmak için çağrılması gereken bir yöntem olduğu garanti edilir (bu şu anda bir RxJs Subscriptionnesnesidir, ancak aslında bağlı olmaması gereken bir uygulama detayıdır).

export class MyServiceEvent {
    message: string;
    eventId: number;
}

export class MyService {
    public onChange: EventEmitter<MyServiceEvent> = new EventEmitter<MyServiceEvent>();

    public doSomething(message: string) {
        // do something, then...
        this.onChange.emit({message: message, eventId: 42});
    }
}

export class MyConsumer {
    private _serviceSubscription;

    constructor(private service: MyService) {
        this._serviceSubscription = this.service.onChange.subscribe({
            next: (event: MyServiceEvent) => {
                console.log(`Received message #${event.eventId}: ${event.message}`);
            }
        })
    }

    public consume() {
        // do some stuff, then later...

        this.cleanup();
    }

    private cleanup() {
        this._serviceSubscription.unsubscribe();
    }
}

Güçlü ifadeli kıyamet ve kasvet tahminlerinin tümü, Angular 2'nin yayın öncesi sürümünde tek bir geliştiriciden gelen tek bir Stack Overflow yorumundan kaynaklanıyor gibi görünüyor.


2
Bu kulağa mantıklı geliyor - başka biri bunu tartmak ister mi? abone ol, olay gönderen herkese açık bir yöntemdir?
Shawson

Tamam, herkese açık, bu yüzden kullanmakta özgürüz. Ancak bu örnekte EventEmitter'ı Observable yerine kullanmak için pratik bir neden var mı?
Botis

6
Şimdi Angular v6 kullanıyoruz ve EventEmmiter kullanımdan kaldırılmadı veya kaldırılmadı, bu yüzden kullanmanın güvenli olduğunu söyleyebilirim. Ancak, RxJS'den Gözlenebilirlerin nasıl kullanılacağını öğrenmenin yararlarını görüyorum.
David Meza

Ben "EventOmitter @Output dışında kullanıyorsanız, api istikrarlı ATM olduğu için başka bir şeye değiştirmek acele gerek yok" olarak görüyorum; zamanınız varsa veya api molalarınız varsa bunu değiştirmeniz gerekecektir (ancak açısal için genel kararlı bir api'yi (yayma ve abone olma) yaygın değildir) unutmayın. Ayrıca genel API'ye sadık kalın, EventEmitter'da tanımlanmayan Konu veya Gözlemlenebilir yöntemlere daha güvenli tarafta kalmak için
erişmeyin

1
"Açısaldan kaldırılmadı" veya "iyi belgelenmiş" nedeniyle bir şeyin kullanımının güvenli olduğu varsayımı ve yukarıda önerilen nono politikası yanlıştır. Açının gelecekteki sürümleri nedeniyle değil bir proje oluşturursunuz. Dışarıda hala web üzerinde çalışan çok sayıda korunmasız platform var. Çerçevenin sürümü, bu platformlarda çalışan geliştiricileri B kategorisinin daha az geliştiricisi veya geliştiricisi yapmaz.
Claudio Ferraro

4

Bileşenler arası etkileşime sahip olmak istediğinizde, @Input, @Output, EventEmitter ve Subjectların ne olduğunu bilmeniz gerekir.

Bileşenler arasındaki ilişki ebeveyn ya da tam tersi ise olay gönderici ile @input & @output kullanırız.

@output bir olay yayar ve olay yayıcı kullanarak yaymanız gerekir.

Ebeveyn-çocuk ilişkisi değilse .. o zaman konuları kullanmanız veya ortak bir servis aracılığıyla yapmanız gerekir.


0

Hayır: nono ve hayır: yesyes. Gerçek ortada ve Angular'ın bir sonraki versiyonu nedeniyle korkmak için hiçbir neden yok.

Mantıksal bir bakış açısından, bir Bileşeniniz varsa ve diğer bileşenleri bir şeyin gerçekleştiği konusunda bilgilendirmek istiyorsanız, bir olay başlatılmalıdır ve bu sizin (geliştirici) bunun yapılması gerektiğini düşündüğü şekilde yapılabilir. Kullanmamanın nedenini görmüyorum ve ne pahasına olursa olsun kullanmamanın nedenini göremiyorum. Ayrıca EventEmitter adı bana bir olay olduğunu gösteriyor. Genellikle Bileşende meydana gelen önemli olaylar için kullanırım. Hizmeti oluşturuyorum ancak Bileşen Klasörü içinde Hizmet dosyasını oluşturuyorum. Hizmet dosyam bir tür Etkinlik Yöneticisi veya Etkinlik Arabirimi haline geldiğinden, geçerli bileşene hangi etkinliğe abone olabileceğimi bir bakışta anlayabilirim.

Biliyorum .. Belki biraz eski moda bir geliştiriciyim. Ancak bu, Olay Odaklı geliştirme modelinin bir parçası değildir, bu, projenizin yazılım mimarisi kararlarının bir parçasıdır.

Diğer bazı erkekler, Gözlemlenebilir öğelerin doğrudan kullanılmasının havalı olduğunu düşünebilir. Bu durumda doğrudan Gözlemlenebilirler ile devam edin. Sen bunu yapan bir seri katil değilsin. Bir psikopat geliştiricisi değilseniz, Şimdiye kadar Program işe yarıyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.