Comment obtenir la valeur actuelle de RxJS sujet ou Observable?
j'ai Angulaire 2 service:
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);
});
}
}
Tout fonctionne très bien. Mais j'ai un autre composant qui n'a pas besoin de souscrire, il a juste besoin d'obtenir la valeur actuelle d'isLoggedIn à un certain moment dans le temps. Comment puis-je faire cela?
5 réponses
Un Subject
ou Observable
n'ont pas de valeur actuelle. Lorsqu'une valeur est émise, elle est transmise aux abonnés et le Observable
en est fait.
si vous voulez avoir une valeur actuelle, utilisez BehaviorSubject
qui est conçu pour exactement ce but. BehaviorSubject
conserve la dernière valeur émise et l'émet immédiatement aux nouveaux abonnés.
Il a aussi une méthode getValue()
pour obtenir la valeur actuelle.
La seule façon de devrait obtenir des valeurs "hors de" Observable/Sujet est à vous abonner!
si vous utilisez getValue()
vous faites quelque chose d'impératif dans le paradigme déclaratif. Il est là comme une trappe d'évacuation, mais 99,9% du temps, vous ne devriez pas utiliser getValue()
. il y a quelques choses intéressantes que getValue()
fera: il lancera une erreur si le sujet a été désabonné, il vous empêchera d'obtenir une valeur si le sujet est morte parce qu'elle est erronée, etc. Mais, encore une fois, il est là comme une issue de secours pour des circonstances rares.
il y a plusieurs façons d'obtenir la valeur la plus récente d'un sujet ou Observable d'une manière "Rx-y":
- utilisant
BehaviorSubject
: mais y souscrivant effectivement . Lorsque vous vous abonnez pour la première fois àBehaviorSubject
, il envoie de façon synchrone la valeur précédente il reçu ou a été initialisé avec. - utilisant un
ReplaySubject(N)
: cela cache les valeursN
et les rejoue aux nouveaux abonnés. -
A.withLatestFrom(B)
: Utilisez cet opérateur pour obtenir la valeur la plus récente deB
observable lorsqueA
émet observable. Vous donnera les deux valeurs dans un tableau[a, b]
. -
A.combineLatest(B)
: Utilisez cet opérateur pour obtenir les valeurs les plus récentes deA
etB
chaque fois queA
ouB
émet. Vous donnera les deux valeurs dans un tableau. -
shareReplay()
: fait une multidiffusion Observable à travers unReplaySubject
, mais vous permet de réessayer l'observable sur erreur. (En gros, cela vous donne ce comportement de mise en cache promise-y). -
publishReplay()
,publishBehavior(initialValue)
,multicast(subject: BehaviorSubject | ReplaySubject)
, etc: autres opérateurs qui tirent surBehaviorSubject
etReplaySubject
. Différentes saveurs de la même chose, ils essentiellement multicast la source observable en canalisant toutes les notifications à travers un sujet. Vous devez appelerconnect()
pour vous abonner à la source avec le sujet.
j'ai eu la même situation où les abonnés tardifs s'abonnent au sujet après que sa valeur soit arrivée.
j'ai trouvé ReplaySubject qui est similaire à BehaviorSubject fonctionne comme un charme dans ce cas. Et voici un lien vers une meilleure explication: http://reactivex.io/rxjs/manual/overview.html#replaysubject
j'ai rencontré le même problème dans les composants enfants où il fallait d'abord avoir la valeur actuelle du sujet, puis s'abonner au sujet pour écouter les changements. Je maintiens juste la valeur actuelle dans le Service de sorte qu'il est disponible pour les composants d'accès, par exemple:
import {Storage} from './storage';
import {Injectable} from 'angular2/core';
import {Subject} from 'rxjs/Subject';
@Injectable()
export class SessionStorage extends Storage {
isLoggedIn: boolean;
private _isLoggedInSource = new Subject<boolean>();
isLoggedIn = this._isLoggedInSource.asObservable();
constructor() {
super('session');
this.currIsLoggedIn = false;
}
setIsLoggedIn(value: boolean) {
this.setItem('_isLoggedIn', value, () => {
this._isLoggedInSource.next(value);
});
this.isLoggedIn = value;
}
}
un composant qui a besoin de la valeur actuelle pourrait alors y accéder à partir du service, I. e,:
sessionStorage.isLoggedIn
Je ne sais pas si c'est le bon practice:)
vous pourriez stocker la dernière valeur émise séparément de L'Observable. Puis de le lire en cas de besoin.
let lastValue: number;
const subscription = new Service().start();
subscription
.subscribe((data) => {
lastValue = data;
}
);