2016-07-28 2 views
9

Ich kann mir vorstellen, dass es möglich wäre, ein Observable zu abonnieren und zu vergessen, sich abzumelden. Ich vermute, das passiert in meiner Bewerbung. Hat das Observable eine Eigenschaft, die mir die Anzahl der Abonnenten anzeigen könnte?In angular2, ist es möglich, eine Anzahl von Abonnenten zu einer beobachtbaren zu erhalten?

+1

Ich denke, die nächste, die Sie bekommen können, ist die Verwendung von .refCount(). https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/refcount.md –

+0

Ich habe basierend auf Ihrer Beschreibung geantwortet, dass Sie Methoden haben möchten, um das Abmelden nicht zu vergessen, wie ich es fühlte war der Kern Ihrer Frage. Es gibt natürlich Möglichkeiten, einen Operator zu schreiben, der tatsächlich helfen würde, zu zählen, aber dies wäre aufgrund der Art und Weise, wie verschiedene Operatoren an verschiedenen Stellen eines Streams teilnehmen könnten, sehr komplex. Hoffentlich gibt meine Antwort Ihnen die Werkzeuge, die Sie brauchen, ohne auf die Meta-Information zu schauen, wie viele Abonnenten es zu einer Observablen gibt. –

Antwort

8

Während es absolut möglich ist, das Abmelden zu vergessen, und die Lecks Folgen haben, die von Testläufern ausgehen, die niemals mit Speicherlecks enden, hat angular2 einige Werkzeuge und Muster zur Verwaltung seines Lebenszyklus.

angular2 bietet eine einfache Möglichkeit, nicht zu vergessen. Der einfachste Weg, wenn Sie in Vorlagen verwendet werden, ist einfach die asynchrone Pipe zu verwenden, die automatisch für Sie abonniert und abbestellt wird.

Wenn Sie andernfalls die Methode .subscribe() verwenden, wird ein Abonnement zurückgegeben. Eine gängige Praxis wäre es, injizierte Abhängigkeiten im Konstruktor zu erfassen, die notwendigen Subskriptionen einer Komponente innerhalb von ngOnInit zu erstellen und innerhalb von ngOnDestroy abzumelden.

Manchmal werden Sie mehrere Observables abonnieren. RxJS stellt die Klasse Rx.Subscription für Gruppenabonnements bereit. Es kann auf folgende Weise verwendet werden:

const incomeSubscription = income$.subscribe(x => console.log(x)); 
const expensesSubscription = expenses$.subscribe(x => console.log(x)); 

const subscription = new Rx.Subscription(); 
subscription.add(incomeSubscription); 
subscription.add(expensesSubscription); 

Jetzt anrufen subscription.unsubscribe() wird abmelden Zeichnungs- noch aktiv.

Schließlich ist es wichtig zu verstehen, dass RxJS-Streams standardmäßig Unicast sind (im Gegensatz zu Versprechungen, die immer die Ergebnisse zwischenspeichern und nur Multicast sind). Dies bedeutet in der Praxis, dass jedes Abonnement tatsächlich zu einem neuen RX-Strom wird. Im Fall von "kalten" Observablen wie Http.get() zum Beispiel, dass jedes Abonnement tatsächlich die Daten von Grund auf neu generiert. In dem erwähnten Fall mit Http.get() werden Sie einen HTTP-Aufruf für jede Subskription (oder Instanz, die die Pipe Async in der Vorlage verwendet) vornehmen.

Dies bedeutet, dass es gute Praxis ist:

  • Nur das Asynchron-Rohr verwenden in einem Container Stil Komponente, und hat stumm Präsentations-Komponenten, die nichts von RxJS wissen. Dies hilft nur

  • Wenn Austausch von Daten zwischen Teilnehmern auf Containerebene zeichnet einen Operator wie .refCount() verwenden in einigen Fällen oder Themen in anderen. Dies macht den Stream Multicast und Abonnenten den gleichen Strom teilen, anstatt haben jeweils ihre eigenen

+1

Mit eckigem v4 ist es eine gute Praxis geworden, das '| zu verwenden async' in Kombination mit 'as secondaryName' (stream $ | async als streamData) Wenn Sie also die Werte einer Observablen mehr als einmal in der Container-Komponente verwenden, abonnieren Sie die Observable nicht mehrfach. –

+0

Ist das Verhalten (möglicher Speicherverlust durch zu viele Subskriptionen) für Angular 5.x.x gleich? –

0

ich dieses Problem hatte und ich löste es durch eine Reihe von Abonnements Aufbau:

import { Subscription } from 'rxjs/Rx'; 

private subValueChanges: Array<Subscription>; 

jedes Mal dann ich unterzeichne, Push in das Array:

this.subValueChanges.push(
    this.someControl.valueChanges 
     .debounceTime(1000) 
     .distinctUntilChanged() 
     .takeUntil(this.destroyValueChanges$) 
     .subscribe (newValue => {...} 
); 

Dann wissen Sie, die Länge des Arrays ist, wie viele Teilnehmer, dass ‚someControl‘ hat.

Ich empfehle es nicht als Lösung, aber es gibt Randfälle, wo dies nützlich sein kann (von denen ich eins hatte).

Interessant ist auch, dass eine Subskription über eine 'geschlossene' Eigenschaft verfügt, die Sie überprüfen können. Wenn sie beispielsweise geschlossen ist, können Sie sie aus dem Array entfernen. Alternativ können Sie beim erstmaligen Anmelden das Ereignis onunsubscribe einrichten, um das Entfernen dieses bestimmten Abonnenten aus dem Array auszulösen. So oder so wird Ihr Array nur aktive Listener enthalten - also sagt Ihnen die Länge immer, wie viele von ihnen da draußen sind! :)

Verwandte Themen