Mam usługę Angular 2:
import {Storage} from './storage';
import {Injectable} from 'angular2/core';
import {Subject} from 'rxjs/Subject';
@Injectable()
export class SessionStorage extends Storage {
private _isLoggedInSource = new Subject<boolean>();
isLoggedIn = this._isLoggedInSource.asObservable();
constructor() {
super('session');
}
setIsLoggedIn(value: boolean) {
this.setItem('_isLoggedIn', value, () => {
this._isLoggedInSource.next(value);
});
}
}
Wszystko działa świetnie. Ale mam inny komponent, który nie musi się subskrybować, musi tylko uzyskać bieżącą wartość isLoggedIn w pewnym momencie. W jaki sposób mogę to zrobić?
javascript
angular
rxjs
Baconbeastnz
źródło
źródło
getValue()
czerwoną flagą, że robisz coś źle. Jest tam jako właz ratunkowy. Ogólnie wszystko, co robisz z RxJS, powinno być deklaratywne.getValue()
jest konieczne. Jeśli używaszgetValue()
, istnieje 99,9% szansy, że zrobisz coś złego lub dziwnego.BehaviorSubject<boolean>(false)
i lubię to przełączać?foo$
byłaBehaviorSubject
(tzn. Jest zdefiniowana jakoObservable
i może jest gorąco lub zimno z odroczonego źródła). Ponieważ jednak później korzystasz.next
z$foo
samego siebie, oznacza to, że twoja implementacja polega na tym, że jestBehaviorSubject
tak, więc nie ma uzasadnienia, aby nie używać tylko.value
uzyskania bieżącej wartości w pierwszej kolejności.Jedyny sposób, w jaki powinny być coraz wartości „z” obserwowanej / Temat jest z zapisz się!
Jeśli używasz
getValue()
, robisz coś imperatywnego w deklaratywnym paradygmacie. Występuje jako właz ewakuacyjny, ale 99,9% czasu NIE powinno się go używaćgetValue()
. Jest kilka interesujących rzeczy, któregetValue()
mogą zrobić: spowoduje zgłoszenie błędu, jeśli temat został wypisany z subskrypcji, zapobiegnie uzyskaniu wartości, jeśli podmiot nie żyje, ponieważ został zignorowany itp. Ale znowu jest to ucieczka wykluć się w rzadkich okolicznościach.Istnieje kilka sposobów uzyskania najnowszej wartości od podmiotu lub obserwacji w sposób „Rx-y”:
BehaviorSubject
: Ale faktycznie subskrybowanie . Po pierwszej subskrypcjiBehaviorSubject
synchronicznie wyśle poprzednią wartość, którą otrzymała lub została zainicjowana.ReplaySubject(N)
: Spowoduje to buforowanieN
wartości i odtworzenie ich nowym subskrybentom.A.withLatestFrom(B)
: Użyj tego operatora, aby uzyskać najnowszą wartość z możliwej do zaobserwowania,B
gdy można ją zaobserwowaćA
. Da ci obie wartości w tablicy[a, b]
.A.combineLatest(B)
: Za pomocą tego operatora, aby uzyskać najnowsze wartości odA
iB
za każdym razem alboA
czyB
emituje. Da ci obie wartości w tablicy.shareReplay()
: Dokonuje obserwowalnej multiemisji przezReplaySubject
, ale umożliwia ponowienie próby zaobserwowania po błędzie. (Zasadniczo daje to obiecujące zachowanie buforowania).publishReplay()
,publishBehavior(initialValue)
,multicast(subject: BehaviorSubject | ReplaySubject)
, Etc: Inni operatorzy że dźwigniaBehaviorSubject
aReplaySubject
. Różne smaki tej samej rzeczy, w zasadzie multiemisję źródła można zaobserwować, kierując wszystkie powiadomienia za pośrednictwem tematu. Musisz zadzwonić,connect()
aby zasubskrybować źródło z tematem.źródło
click$.mergeMap(() => behaviorSubject.take(1))
rozwiązać problem.AuthenticationService
który używa aBehaviourSubject
do przechowywania bieżącego zalogowanego stanu (boolean
true
lubfalse
). Odsłania toisLoggedIn$
obserwowalne dla subskrybentów, którzy chcą wiedzieć, kiedy zmienia się stan. Udostępnia takżeget isLoggedIn()
właściwość, która zwraca bieżący stan zalogowania, wywołującgetValue()
bazęBehaviourSubject
- jest to używane przez mojego strażnika uwierzytelnienia do sprawdzenia bieżącego stanu. Wydaje mi się to rozsądnym zastosowaniemgetValue()
...?Miałem podobną sytuację, w której spóźnieni subskrybenci subskrybują Temat po otrzymaniu jego wartości.
Znalazłem ReplaySubject, który jest podobny do BehaviorSubject działa w tym przypadku jak urok. A oto link do lepszego wyjaśnienia: http://reactivex.io/rxjs/manual/overview.html#replaysubject
źródło
next()
funkcja nie została jeszcze wywołana, podczas gdy BehaviourSubject tak. Natychmiastowa emisja jest bardzo przydatna do zastosowania wartości domyślnych do widoku, gdy BehaviourSubject jest używany jako źródło danych obserwowalne w usłudze, na przykładMożesz sprawdzić pełny artykuł o tym, jak go wdrożyć tutaj. https://www.imkrish.com/how-to-get-current-value-of-observable-in-a-clean-way/
źródło
Ten sam problem napotkałem w komponentach potomnych, gdzie początkowo musiałby mieć bieżącą wartość Przedmiotu, a następnie zasubskrybować Temat, aby słuchać zmian. Po prostu utrzymuję bieżącą wartość w usłudze, aby była dostępna dla komponentów, na przykład:
Komponent, który potrzebuje bieżącej wartości, może właśnie uzyskać dostęp do niej z usługi, tj .:
Nie jestem pewien, czy to dobra praktyka :)
źródło
async
potoku.Podobna patrząc odpowiedź została downvoted. Ale myślę, że mogę uzasadnić to, co sugeruję tutaj w ograniczonych przypadkach.
Chociaż prawdą jest, że obserwowalne nie ma bieżącej wartości, bardzo często będzie miało natychmiast dostępną wartość. Na przykład w sklepach redux / flux / akita możesz zażądać danych ze sklepu centralnego, w oparciu o pewną liczbę obserwowalnych, a ta wartość będzie na ogół natychmiast dostępna.
Jeśli tak jest, to kiedy Ty
subscribe
, wartość natychmiast wróci.Powiedzmy, że masz połączenie z usługą, a po zakończeniu chcesz uzyskać najnowszą wartość czegoś ze swojego sklepu, który potencjalnie może nie emitować :
Możesz spróbować to zrobić (i powinieneś w miarę możliwości trzymać rzeczy „wewnątrz rur”):
Problem polega na tym, że blokuje się, dopóki obserwowalne wtórne nie wyemituje wartości, która potencjalnie może nigdy nie być.
Niedawno stwierdziłam, że muszę ocenić obserwowalne tylko wtedy, gdy wartość jest natychmiast dostępna , a co ważniejsze, muszę być w stanie wykryć, czy nie była. Skończyło się na tym, że:
Zauważ, że dla wszystkich powyższych używam,
subscribe
aby uzyskać wartość (jak omawia @Ben). Nie korzystam z.value
nieruchomości, nawet gdybym miałBehaviorSubject
.źródło
Chociaż może to zabrzmieć przesadnie, jest to kolejne „możliwe” rozwiązanie pozwalające zachować typ obserwowalny i zmniejszyć płytę kotłową ...
Zawsze możesz utworzyć moduł pobierający rozszerzenia, aby uzyskać bieżącą wartość Obserwowalnego.
Aby to zrobić, musisz rozszerzyć
Observable<T>
interfejs wglobal.d.ts
pliku deklaracji typów. Następnie wdrożyć getter rozszerzenie wobservable.extension.ts
pliku i wreszcie obejmować zarówno typowania i plik rozszerzenia do aplikacji.Możesz zapoznać się z tą odpowiedzią StackOverflow, aby dowiedzieć się, jak dołączyć rozszerzenia do aplikacji Angular.
źródło
Możesz przechowywać ostatnią emitowaną wartość oddzielnie od Obserable. Następnie przeczytaj go w razie potrzeby.
źródło
Najlepszym sposobem na to jest użycie
Behaviur Subject
, oto przykład:źródło
Subskrypcję można utworzyć i po zniszczeniu pierwszego emitowanego przedmiotu. Rura jest funkcją, która wykorzystuje Obserowalny jako swój sygnał wejściowy i zwraca inny Obserowalny jako wynik, nie modyfikując jednak pierwszego obserwowalnego. Kątowy 8.1.0. Pakiety:
"rxjs": "6.5.3"
,"rxjs-observable": "0.0.7"
źródło