Kiedy należy przechowywać Subscription
instancje i wywoływać je unsubscribe()
podczas cyklu życia NgOnDestroy, a kiedy mogę je po prostu zignorować?
Zapisanie wszystkich subskrypcji wprowadza sporo bałaganu do kodu komponentu.
Przewodnik klienta HTTP ignoruje takie subskrypcje:
getHeroes() {
this.heroService.getHeroes()
.subscribe(
heroes => this.heroes = heroes,
error => this.errorMessage = <any>error);
}
W tym samym czasie Przewodnik trasy i nawigacji mówi:
W końcu będziemy nawigować gdzie indziej. Router usunie ten składnik z DOM i zniszczy go. Musimy po sobie posprzątać, zanim to nastąpi. W szczególności musimy anulować subskrypcję, zanim Angular zniszczy komponent. Niezastosowanie się do tego może spowodować wyciek pamięci.
Możemy zrezygnować z naszych
Observable
wngOnDestroy
metodzie.
private sub: any;
ngOnInit() {
this.sub = this.route.params.subscribe(params => {
let id = +params['id']; // (+) converts string 'id' to a number
this.service.getHero(id).then(hero => this.hero = hero);
});
}
ngOnDestroy() {
this.sub.unsubscribe();
}
angular
rxjs
observable
subscription
angular-component-life-cycle
Sergey Tihon
źródło
źródło
Subscription
s, abyhttp-requests
można zignorować, jak nazywają tylkoonNext
raz, a potem nazywająonComplete
.Router
Zamiast nazywaonNext
wielokrotnie i nigdy nie może zadzwonićonComplete
(nie wiem o tym ...). To samo dotyczyObservable
s odEvent
s. Sądzę, że tak powinno byćunsubscribed
.subscribe
siebie, które potencjalnie alokuje zasoby na wcześniejszym etapie.Odpowiedzi:
--- Edycja 4 - Dodatkowe zasoby (2018/09/01)
W ostatnim odcinku Adventures in Angular Ben Lesh i Ward Bell dyskutują na temat tego, jak / kiedy wypisać się z komponentu. Dyskusja rozpoczyna się około 1:05:30.
Totem wspomina,
right now there's an awful takeUntil dance that takes a lot of machinery
a Shai Reznik wspominaAngular handles some of the subscriptions like http and routing
.W odpowiedzi Ben wspomina, że obecnie trwają dyskusje, aby umożliwić obserwatorom przyłączenie się do zdarzeń cyklu życia komponentu kątowego, a Ward sugeruje obserwowalność zdarzeń cyklu życia, do których komponent może się zapisać, aby dowiedzieć się, kiedy ukończyć obserwowalne utrzymywane jako stan wewnętrzny komponentu.
To powiedziawszy, teraz potrzebujemy rozwiązań, więc oto inne zasoby.
Rekomendacja
takeUntil()
wzoru autorstwa członka zespołu RxJ, Nicholasa Jamiesona, oraz reguła tslint, aby pomóc w egzekwowaniu go. https://ncjamieson.com/avoiding-takeuntil-leaks/Lekki pakiet npm, który ujawnia obserwowalny operator, który przyjmuje instancję składnika (
this
) jako parametr i automatycznie wypisuje się podczasngOnDestroy
. https://github.com/NetanelBasal/ngx-take-until-destroyKolejna odmiana powyższego z nieco lepszą ergonomią, jeśli nie robisz kompilacji AOT (ale wszyscy powinniśmy teraz robić AOT). https://github.com/smnbbrv/ngx-rx-collector
Niestandardowa dyrektywa,
*ngSubscribe
która działa jak potok asynchroniczny, ale tworzy widok osadzony w szablonie, dzięki czemu można odwoływać się do wartości „nieopakowanej” w całym szablonie. https://netbasal.com/diy-subscription-handling-directive-in-angular-c8f6e762697fWspominam w komentarzu na blogu Nicholasa, że nadużywanie
takeUntil()
może być oznaką, że twój komponent próbuje zrobić zbyt wiele i że należy rozważyć rozdzielenie istniejących komponentów na komponenty Feature i Presentation . Następnie można| async
obserwować z komponentu Feature doInput
komponentu Presentation, co oznacza, że nigdzie nie są potrzebne subskrypcje. Przeczytaj więcej o tym podejściu tutaj--- Edytuj 3 - „Oficjalne” rozwiązanie (2017/04/09)
Rozmawiałem z Wardem Bellem na temat tego pytania w NGConf (nawet pokazałem mu tę odpowiedź, która, jak powiedział, była poprawna), ale powiedział mi, że zespół doktorów Angular ma rozwiązanie tego pytania, które nie zostało opublikowane (chociaż pracują nad tym, aby je zatwierdzić) ). Powiedział mi również, że mogę zaktualizować moją odpowiedź SO wraz z nadchodzącą oficjalną rekomendacją.
Rozwiązaniem, którego powinniśmy wszyscy użyć w przyszłości, jest dodanie
private ngUnsubscribe = new Subject();
pola do wszystkich komponentów, które mają.subscribe()
wywołaniaObservable
s w swoim kodzie klasy.Następnie wywołujemy
this.ngUnsubscribe.next(); this.ngUnsubscribe.complete();
naszengOnDestroy()
metody.Tajny sos (jak już zauważył @metamaker ) ma wywoływać
takeUntil(this.ngUnsubscribe)
przed każdym z naszych.subscribe()
połączeń, co zagwarantuje, że wszystkie subskrypcje zostaną wyczyszczone po zniszczeniu komponentu.Przykład:
Uwaga: Ważne jest, aby dodać
takeUntil
operatora jako ostatni, aby zapobiec wyciekom z pośrednimi obserwowalnymi w łańcuchu operatora.--- Edytuj 2 (2016/12/28)
Źródło 5
W samouczku Angular, rozdział Routing stwierdza teraz: „Router zarządza obserwowanymi przez siebie obiektami i lokalizuje subskrypcje. Subskrypcje są czyszczone po zniszczeniu komponentu, chroniąc przed wyciekiem pamięci, więc nie musimy rezygnować z subskrypcji trasa jest możliwa do zaobserwowania. ” - Mark Rajcok
Oto dyskusja na temat Github dla dokumentów Angular dotyczących Router Observables, w której Ward Bell wspomina, że wyjaśnienie tego wszystkiego znajduje się w pracach.
--- Edytuj 1
Źródło 4
W tym filmie NgEurope Rob Wormald mówi również, że nie musisz rezygnować z subskrypcji Router Observables. Wspomina także o
http
usłudze orazActivatedRoute.params
w tym filmie z listopada 2016 r .--- Oryginalna odpowiedź
TLDR:
Dla tego pytania istnieją (2) rodzaje
Observables
- wartość skończona i wartość nieskończona .http
Observables
tworzy wartości skończone (1) i coś w rodzaju DOMevent listener
Observables
tworzy wartości nieskończone .Jeśli ręcznie wywołujesz
subscribe
(nie używając potoku asynchronicznego), tounsubscribe
z nieskończonościObservables
.Nie przejmuj się skończonymi ,
RxJs
zajmę się nimi.Źródło 1
Tutaj odnalazłem odpowiedź Roba Wormalda w Angular's Gitter .
Mówi (zreorganizowałem dla jasności i podkreślenia jest moje)
Wspomina również w tym filmie na YouTubie o Observables, który
they clean up after themselves
... w kontekście Observables, którecomplete
(jak Obietnice, które zawsze się kończą, ponieważ zawsze generują 1 wartość i kończą się - nigdy nie martwiliśmy się o rezygnację z subskrypcji Obietnic, aby upewnić się, że posprzątająxhr
wydarzenie słuchacze, prawda?).Źródło 2
Również w przewodniku Rangle do Angulara 2 czytamy
Kiedy to wyrażenie ma
our Observable has a longer lifespan than our subscription
zastosowanie?Ma to zastosowanie, gdy subskrypcja jest tworzona wewnątrz komponentu, który jest niszczony przed (lub „długo” przed)
Observable
zakończeniem.Czytam to jako znaczące, że jeśli zasubskrybujemy
http
żądanie lub obserwowalny, który emituje 10 wartości, a nasz komponent zostanie zniszczony przedhttp
zwróceniem tego żądania lub wysłaniem 10 wartości, nadal mamy się dobrze!Gdy żądanie zostanie zwrócone lub dziesiąta wartość zostanie ostatecznie wysłana,
Observable
zostanie zakończone, a wszystkie zasoby zostaną oczyszczone.Źródło 3
Jeśli spojrzymy na ten przykład z tego samego rangle kierować widzimy, że
Subscription
abyroute.params
nie wymagaćunsubscribe()
, bo nie wiemy, kiedy teparams
przestaną zmianę (emitując nowe wartości).Komponent może zostać zniszczony przez odejście, w którym to przypadku parametry trasy prawdopodobnie nadal będą się zmieniać (mogą technicznie zmieniać się aż do końca aplikacji), a zasoby przydzielone w subskrypcji będą nadal przydzielone, ponieważ nie było
completion
.źródło
complete()
sama w sobie nie wydaje się, aby oczyścić subskrypcji. Jakkolwiek wywołanie,next()
a następniecomplete()
zadziałanie, uważam, żetakeUntil()
zatrzymuje się tylko po wygenerowaniu wartości, a nie po zakończeniu sekwencji.Subject
wewnątrz komponentu i przełączaniem go wngIf
celu wyzwoleniangOnInit
ingOnDestroy
pokazania, że podmiot i jego subskrypcje nigdy się nie zakończą ani nie zostaną zutylizowane (podłączyłyfinally
operatora do subskrypcji). Muszę zadzwonićSubject.complete()
wngOnDestroy
tak subskrypcje mogą posprzątać po sobie.takeUnitl
podejścia, nigdy nie musimy ręcznie rezygnować z subskrypcji żadnych obserwowalnych obiektów? Czy tak jest w przypadku? Ponadto, dlaczego musimy wywołaćnext()
wngOnDestroy
, dlaczego po prostu nie zadzwonićcomplete()
?Nie musisz mieć wielu subskrypcji i ręcznie zrezygnować z subskrypcji. Użyj komendy Subject i takeUntil do obsługi subskrypcji jak szef:
Alternatywne podejście , które zostało zaproponowane przez @acumartini w komentarzach , wykorzystuje takeWhile zamiast takeUntil . Możesz to preferować, ale pamiętaj, że w ten sposób twoje obserwowalne wykonanie nie zostanie anulowane po ngDestroy twojego komponentu (np. Gdy wykonujesz czasochłonne obliczenia lub czekasz na dane z serwera). Metoda oparta na takeUntil nie ma tej wady i prowadzi do natychmiastowego anulowania żądania. Dzięki @AlexChe za szczegółowe wyjaśnienia w komentarzach .
Oto kod:
źródło
takeUntil
atakeWhile
. Pierwszy wypisuje się ze źródła obserwowalnego natychmiast po wystrzeleniu, podczas gdy drugi wypisuje się dopiero, gdy następna wartość zostanie wygenerowana przez obserwowalne źródło. Jeśli generowanie wartości przez obserwowalne źródło jest operacją pochłaniającą zasoby, wybranie jednego z nich może wykraczać poza preferencje stylu. Zobacz plunktakeUntil
vstakeWhile
, jednak nie w naszym konkretnym przypadku. Kiedy musimy anulować subskrypcję detektorów po zniszczeniu komponentu , sprawdzamy po prostu wartość boolowską , tak jak() => alive
wtakeWhile
, więc żadne operacje zajmujące czas / pamięć nie są używane, a różnica dotyczy głównie stylizacji (ofc, w tym konkretnym przypadku).Observable
, która wewnętrznienext
wydobywa kryptowalutę i wystrzeliwuje wydarzenie dla każdej wydobytej monety, a wydobycie jednej takiej monety zajmuje dzień. DziękitakeUntil
wypisamy się ze źródła wydobycieObservable
natychmiast pongOnDestroy
wywołaniu podczas niszczenia naszego komponentu. W ten sposóbObservable
funkcja wyszukiwania może natychmiast anulować działanie podczas tego procesu.takeWhile
, pongOnDestory
prostu ustawiamy zmienną boolowską. AleObservable
funkcja wyszukiwania może nadal działać przez jeden dzień i dopiero wtedy podczasnext
połączenia zda sobie sprawę, że nie ma aktywnych subskrypcji i musi zostać anulowana.Klasa subskrypcji ma ciekawą funkcję:
Możesz utworzyć zagregowany obiekt subskrypcji, który grupuje wszystkie twoje subskrypcje. Robisz to, tworząc pustą subskrypcję i dodając do niej subskrypcje za pomocą jej
add()
metody. Gdy twój komponent zostanie zniszczony, wystarczy anulować subskrypcję subskrypcji zbiorczej.źródło
takeUntil
podejścia w porównaniu z tym podejściem polegającym na pobieraniu subskrypcji i telefonowaniuunsubscribe
. (To podejście wydaje mi się o wiele czystsze.)this.subscriptions
jest pustasub = subsciption.add(..).add(..)
ponieważ w wielu przypadkach daje nieoczekiwane wyniki github.com/ReactiveX/rxjs/issues/2769#issuecomment-345636477Niektóre z najlepszych praktyk dotyczących anulowania subskrypcji obserwowalnych w komponentach Angular:
Cytat z
Routing & Navigation
I odpowiadając na następujące linki:
http
obserwowalnegoZebrałem niektóre najlepsze praktyki dotyczące rezygnacji z obserwowalnych elementów wewnątrz Angular, aby podzielić się z Tobą:
http
obserwowalna rezygnacja z subskrypcji jest warunkowa i powinniśmy rozważyć skutki uruchomienia wywołania zwrotnego subskrypcji po zniszczeniu komponentu w poszczególnych przypadkach. Wiemy, że kątowy wypisuje się i czyścihttp
samo obserwowalne (1) , (2) . Chociaż jest to prawda z punktu widzenia zasobów, opowiada tylko połowę historii. Powiedzmy, że mówimy o bezpośrednim wywoływaniuhttp
z komponentu, ahttp
odpowiedź zajęła więcej czasu, niż to konieczne, więc użytkownik zamknął komponent. Thesubscribe()
moduł obsługi będzie nadal wywoływany, nawet jeśli komponent jest zamknięty i zniszczony. Może to mieć niepożądane skutki uboczne, aw gorszych scenariuszach stan aplikacji jest zepsuty. Może również powodować wyjątki, jeśli kod w wywołaniu zwrotnym próbuje wywołać coś, co zostało właśnie usunięte. Jednak jednocześnie są one pożądane. Załóżmy, że tworzysz klienta poczty e-mail i uruchamiasz dźwięk po zakończeniu wysyłania wiadomości e-mail - nadal chcesz, aby tak się stało, nawet jeśli składnik jest zamknięty ( 8 ).AsyncPipe
jak najwięcej, ponieważ automatycznie wypisuje się z obserwowalnego zniszczenia elementu.ActivatedRoute
obserwowalnych, takroute.params
jakby subskrybowano je w zagnieżdżonym (dodanym w tpl z selektorem komponentów) lub komponencie dynamicznym, ponieważ mogą być subskrybowane wiele razy, dopóki istnieje komponent nadrzędny / host. Nie ma potrzeby wypisywania się z nich w innych scenariuszach, jak wspomniano w cytacie powyżej zRouting & Navigation
dokumentów.Uwaga: Jeśli chodzi o usługi o zasięgu, tj. Dostawców komponentów, są one niszczone po zniszczeniu komponentu. W takim przypadku, jeśli zasubskrybujemy jakąkolwiek obserwowalną wewnątrz tego dostawcy, powinniśmy rozważyć rezygnację z subskrypcji za pomocą
OnDestroy
haka cyklu życia, który zostanie wywołany, gdy usługa zostanie zniszczona, zgodnie z dokumentacją.takeUntil
(3) lub możesz użyć tegonpm
pakietu wymienionego w (4) Najprostszym sposobem na wypisanie się z listy Obserwowalnych w Angular .FormGroup
obserwowalnych obiektów, takich jakform.valueChanges
iform.statusChanges
Renderer2
usług, takich jakrenderer2.listen
HostListener
ponieważ Angular dobrze dba o usunięcie detektorów zdarzeń w razie potrzeby i zapobiega potencjalnemu wyciekowi pamięci z powodu powiązań zdarzeń.Dobra końcowa wskazówka : jeśli nie wiesz, czy obserwowalne jest automatycznie anulowane / ukończone, czy nie, dodaj
complete
oddzwonieniesubscribe(...)
i sprawdź, czy zostanie wywołane, gdy element zostanie zniszczony.źródło
ngOnDestroy
wywoływanie następuje, gdy usługa jest świadczona na poziomie innym niż poziom główny, np. Jest jawnie udostępniana w komponencie, który później zostaje usunięty. W takich przypadkach należy zrezygnować z subskrypcji wewnętrznych usług obserwacyjnychngOnDestroy
, który jest zawsze o nazwie gdy usługi są zniszczone github.com/angular/angular/commit/...Feel free to unsubscribe anyway. It is harmless and never a bad practice.
i jeśli chodzi o twoje pytanie, to zależy. Jeśli komponent potomny jest inicjowany wiele razy (na przykład dodawany wewnątrzngIf
lub ładowany dynamicznie), należy anulować subskrypcję, aby uniknąć dodawania wielu subskrypcji do tego samego obserwatora. W przeciwnym razie nie ma takiej potrzeby. Ale wolę wypisać się z komponentu potomnego, ponieważ sprawia, że jest on bardziej wielokrotnego użytku i odizolowany od tego, jak można go używać.To zależy. Jeśli dzwoniąc
someObservable.subscribe()
, zaczniesz utrzymywać zasób, który trzeba ręcznie zwolnić po zakończeniu cyklu życia komponentu, powinieneś zadzwonić,theSubscription.unsubscribe()
aby zapobiec wyciekom pamięci.Przyjrzyjmy się bliżej twoim przykładom:
getHero()
zwraca wynik zhttp.get()
. Jeśli spojrzysz na kod źródłowy Angular 2 ,http.get()
stwórz dwa detektory zdarzeń:i dzwoniąc
unsubscribe()
, możesz anulować żądanie, a także słuchaczy:Pamiętaj, że
_xhr
jest to specyficzne dla platformy, ale myślę, że można bezpiecznie założyć, że jest toXMLHttpRequest()
w twoim przypadku.Zwykle jest to wystarczający dowód, aby uzasadnić ręczne
unsubscribe()
połączenie. Ale zgodnie z tą specyfikacją WHATWG ,XMLHttpRequest()
po „skończeniu” podlega on odśmiecaniu, nawet jeśli są do niego dołączone detektory zdarzeń. Sądzę więc, że dlatego oficjalny poradnik Angular 2 pomijaunsubscribe()
i pozwala GC posprzątać słuchaczy.Jeśli chodzi o twój drugi przykład, zależy to od implementacji
params
. Na dzień oficjalny przewodnik kątowy nie pokazuje już rezygnacji z subskrypcjiparams
. Znów zajrzałem do src i stwierdziłem, żeparams
jest to po prostu BehaviorSubject . Ponieważ nie użyto żadnych detektorów zdarzeń ani timerów ani nie utworzono żadnych zmiennych globalnych, należy bezpiecznie je pominąćunsubscribe()
.Najważniejsze w twoim pytaniu jest to, że zawsze zadzwoń
unsubscribe()
jako zabezpieczenie przed wyciekiem pamięci, chyba że masz pewność, że wykonanie obserwowalnego nie tworzy zmiennych globalnych, nie dodaje detektorów zdarzeń, ustawia liczniki czasu lub robi cokolwiek innego, co powoduje wycieki pamięci .W razie wątpliwości przyjrzyj się realizacji tego obserwowalnego. Jeśli to, co obserwowalne, zapisało w niej trochę logiki czyszczenia
unsubscribe()
, która zwykle jest funkcją zwracaną przez konstruktora, masz dobry powód, aby poważnie rozważyć wywołanieunsubscribe()
.źródło
Oficjalna dokumentacja Angular 2 zawiera wyjaśnienie, kiedy wypisać się, a kiedy można ją bezpiecznie zignorować. Spójrz na ten link:
https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service
Poszukaj akapitu z nagłówkiem Rodzice i dzieci komunikują się za pośrednictwem usługi, a następnie niebieskiego pola:
Mam nadzieję, że to Ci pomoże.
źródło
Na podstawie: Korzystanie z dziedziczenia klas w celu dołączenia do cyklu życia komponentu Angular 2
Inne ogólne podejście:
I użyć :
źródło
this.componentDestroyed$.next()
połączenia takiego jak zaakceptowane rozwiązanie przez Sean powyżej ...Oficjalna odpowiedź na edycję nr 3 (i jej odmiany) działa dobrze, ale to, co mnie przyciąga, to „mętnienie” logiki biznesowej wokół obserwowalnej subskrypcji.
Oto inne podejście przy użyciu opakowań.
Plik subscribeAndGuard.ts służy do utworzenia nowego Obserowalnego rozszerzenia do zawinięcia
.subscribe()
oraz w nim do zawinięciangOnDestroy()
.Użycie jest takie samo
.subscribe()
, z wyjątkiem dodatkowego pierwszego parametru odnoszącego się do komponentu.Oto komponent z dwiema subskrypcjami, jedną z opakowaniem, a drugą bez. Jedynym zastrzeżeniem jest to, że musi implementować OnDestroy (z pustym ciałem, jeśli jest to pożądane), w przeciwnym razie Angular nie wie, aby wywołać wersję owiniętą.
Plunker demo jest tutaj
Dodatkowa uwaga: Re Edycja 3 - „Oficjalne” rozwiązanie, można to uprościć, używając takeWhile () zamiast takeUntil () przed subskrypcjami, oraz prostą wartość logiczną zamiast innej możliwej do zaobserwowania w ngOnDestroy.
źródło
Ponieważ rozwiązanie seangwrighta (Edycja 3) wydaje się bardzo przydatne, trudno mi było spakować tę funkcję do komponentu podstawowego i zasugerować innym członkom zespołu, aby pamiętali o wywołaniu super () na ngOnDestroy, aby aktywować tę funkcję.
Ta odpowiedź zapewnia sposób na uwolnienie się od super połączeń i uczynienie „componentDestroyed $” rdzeniem podstawowego komponentu.
Następnie możesz swobodnie korzystać z tej funkcji, na przykład:
źródło
Zgodnie z odpowiedzią @seangwright napisałem abstrakcyjną klasę, która obsługuje subskrypcje „nieskończonych” obserwowalnych w komponentach:
Aby go użyć, po prostu rozciągnij go w składniku kątowym i wywołaj
subscribe()
metodę w następujący sposób:Akceptuje także błąd i kompletne wywołania zwrotne, jak zwykle, obiekt obserwatora lub wcale nie wywołań zwrotnych. Pamiętaj, aby zadzwonić,
super.ngOnDestroy()
jeśli implementujesz tę metodę również w komponencie potomnym.Znajdź tutaj dodatkowe odniesienie autorstwa Ben Lesh: RxJS: Don't Unsubscribe .
źródło
Próbowałem rozwiązania Seangwrighta (edycja 3)
To nie działa w przypadku Observable utworzonego przez timer lub interwał.
Udało mi się to jednak przy użyciu innego podejścia:
źródło
I podobnie jak w ostatnich dwóch odpowiedzi, ale wystąpił problem, gdy podklasa odwołuje
"this"
sięngOnDestroy
.Zmodyfikowałem go tak, aby wyglądał tak, i wygląda na to, że rozwiązał ten problem.
źródło
this.ngOnDestroy = () => { f.bind(this)(); this.componentDestroyed$.complete(); };
W przypadku konieczności rezygnacji z subskrypcji można zastosować następujący operator metody obserwowalnej rury
można go użyć w następujący sposób:
Operator otacza metodę ngOnDestroy komponentu.
Ważne: operator powinien być ostatnim obserwowalnym przewodem.
źródło
Zwykle musisz zrezygnować z subskrypcji, gdy komponenty zostaną zniszczone, ale Angular będzie sobie z tym radził coraz częściej, na przykład w nowej, mniejszej wersji Angular4, mają one sekcję do anulowania subskrypcji:
Również poniższy przykład jest dobrym przykładem Angulara do tworzenia komponentu i niszczenia go po, zobacz, jak komponent implementuje OnDestroy, jeśli potrzebujesz onInit, możesz również zaimplementować go w komponencie, podobnie jak implementacje
OnInit, OnDestroy
źródło
Kolejnym krótkim dodatkiem do wyżej wymienionych sytuacji jest:
źródło
w aplikacji SPA w funkcji ngOnDestroy (kątowy cykl życia) Dla każdej subskrypcji należy ją anulować . korzyść =>, aby zapobiec zbyt dużemu stanowi.
na przykład: w komponencie 1:
czynny:
w komponencie 2:
źródło
Do obsługi subskrypcji używam klasy „Unsubscriber”.
Oto klasa Unsubscriber.
I możesz użyć tej klasy w dowolnym komponencie / usłudze / efekcie itp.
Przykład:
źródło
Możesz użyć najnowszej
Subscription
klasy, aby wypisać się z listy Obserwowalnych z niezbyt brudnym kodem.Możemy to zrobić,
normal variable
ale będzie tooverride the last subscription
przy każdym nowym abonamencie, więc unikaj tego, a to podejście jest bardzo przydatne, gdy masz do czynienia z większą liczbą Obseravable, i typem Obeservable, takim jakBehavoiurSubject
iSubject
Subskrypcja
możesz użyć tego na dwa sposoby,
możesz bezpośrednio przekazać subskrypcję do tablicy subskrypcji
korzystanie
add()
zSubscription
Subscription
Może posiadać subskrypcje potomnych i bezpiecznie je wszystkie wypisać. Ta metoda obsługuje możliwe błędy (np. Jeśli dowolna subskrypcja podrzędna ma wartość NULL).Mam nadzieję że to pomoże.. :)
źródło
Pakiet SubSink, łatwe i spójne rozwiązanie do rezygnacji z subskrypcji
Jak nikt inny o tym nie wspomniał, chcę polecić pakiet Subsink stworzony przez Ward Bell: https://github.com/wardbell/subsink#readme .
Używałem go w projekcie, gdy wszyscy jesteśmy programistami. Bardzo pomaga mieć spójny sposób działania w każdej sytuacji.
źródło
W przypadku obserwowalnych, które wypełniają się bezpośrednio po wyemitowaniu wyniku, takich jak
AsyncSubject
np. Obserwowalne z żądań HTTP i takie nie trzeba anulować subskrypcji. Wzywanie do nich nie zaszkodziunsubscribe()
, ale jeśli można to zaobserwować,closed
metoda rezygnacji z subskrypcji po prostu nic nie zrobi :Jeśli masz długotrwałe obserwowalne, które emitują kilka wartości w czasie (np. A
BehaviorSubject
lub aReplaySubject
), musisz anulować subskrypcję, aby zapobiec wyciekom pamięci.Możesz łatwo stworzyć obserwowalne, które kończy się bezpośrednio po wyemitowaniu wyniku z tak długowiecznych obserwowalnych za pomocą operatora potoku. W niektórych odpowiedziach
take(1)
wspomniana jest rura. Ale wolę sięfirst()
rury . Różnicatake(1)
polega na tym, że:Kolejną zaletą pierwszego potoku jest to, że możesz przekazać predykat, który pomoże ci zwrócić pierwszą wartość, która spełnia określone kryteria:
Pierwszy zakończy się bezpośrednio po emisji pierwszej wartości (lub po przekazaniu argumentu funkcji pierwszej wartości, która spełnia predykat), więc nie ma potrzeby anulowania subskrypcji.
Czasami nie masz pewności, czy możesz obserwować długo, czy nie. Nie twierdzę, że jest to dobra praktyka, ale zawsze możesz dodać
first
rurkę, aby upewnić się, że nie będziesz musiał ręcznie anulować subskrypcji. Dodanie dodatkowejfirst
rury na obserwowalnym, która wyemituje tylko jedną wartość, nie zaszkodzi.Podczas rozwoju można użyć do
single
rury , która będzie zawodzić, jeśli źródłowych obserwowalnych emituje kilku zdarzeń. Może to pomóc w zbadaniu rodzaju obserwowalnego i tego, czy konieczne jest zrezygnowanie z niego, czy nie.first
Isingle
wydają się bardzo podobne, oba przewody mogą opcjonalnego predykatu ale różnice są ważne i ładnie podsumowane w tej stackoverflow odpowiedź tutaj :Uwaga: W mojej odpowiedzi starałem się być jak najbardziej dokładny i kompletny z odniesieniami do oficjalnej dokumentacji, ale proszę o komentarz, jeśli brakuje czegoś ważnego ...
źródło
--- Zaktualizuj rozwiązanie Angular 9 i Rxjs 6
unsubscribe
wngDestroy
cyklu życia elementu kątowegotakeUntil
w RxjsngOnInit
, zdarzają się tylko raz, gdy inicjuje się komponent.Mamy też
async
fajkę. Ale to użycie na szablonie (nie w komponencie Angular).źródło