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);
});
}
}
すべてうまくいっています。しかし、購読する必要のない別のコンポーネントがあります。特定の時点でisLoggedInの現在の値を取得するだけです。これどうやってするの?
Subject
またはObservable
は現在の値を持ちません。値が発行されると、それはサブスクライバに渡され、それとともにObservable
が行われます。
現在の値を取得したい場合は、その目的のために設計されたBehaviorSubject
を使用してください。 BehaviorSubject
は最後に発行された値を保持し、それを直ちに新しい購読者に発行します。
現在の値を取得するためのメソッドgetValue()
もあります。
getValue()
を使用している場合は、宣言的なパラダイムで必須のことをしています。エスケープハッチとしてありますが、99.9%のgetValue()
を使用すべきではありませんgetValue()
が行う興味深いことがいくつかあります:エラーをスローしますサブジェクトがサブスクライブされていない場合、エラーなどのためにサブジェクトが死んでいる場合、値を取得できなくなります。しかし、まれに、エスケープハッチとして存在します。
「Rx-y」の方法でSubjectまたはObservableから最新の値を取得するには、いくつかの方法があります。
BehaviorSubject
の使用:しかし実際にサブスクライブする。最初にBehaviorSubject
をサブスクライブすると、受信した、または初期化された前の値が同期的に送信されます。ReplaySubject(N)
の使用:これはN
値をキャッシュし、それらを新しいサブスクライバーにリプレイします。A.withLatestFrom(B)
:この演算子を使用して、オブザーバブルB
が放出されたときに、オブザーバブルA
から最新の値を取得します。配列[a, b]
の両方の値を提供します。A.combineLatest(B)
:この演算子を使用して、A
またはB
が出力するたびに、A
およびB
から最新の値を取得します。両方の値を配列で提供します。shareReplay()
:ReplaySubject
を介してObservableマルチキャストを作成しますが、エラー時にObservableを再試行できます。 (基本的には、promise-yキャッシュ動作を提供します)。publishReplay()
、publishBehavior(initialValue)
、multicast(subject: BehaviorSubject | ReplaySubject)
など:BehaviorSubject
およびReplaySubject
を活用する他の演算子。同じことの異なるフレーバー、それらは基本的に、サブジェクトを介してすべての通知を集中させることにより、観測可能なソースをマルチキャストします。 connect()
を呼び出して、件名でソースをサブスクライブする必要があります。私は、値が到着した後に遅い購読者が件名を購読するという同様の状況を経験しました。
BehaviorSubjectに似ている ReplaySubject は、この場合魅力のように動作します。そして、これはより良い説明へのリンクです: http://reactivex.io/rxjs/manual/overview.html#replaysubject
私は最初はSubjectの現在の値を持っていなければならない子コンポーネントで同じ問題に遭遇しましたそしてそれから変更を聞くためにSubjectを購読します。私はサービス内の現在の値を維持するので、コンポーネントがアクセスできるようにします。 :
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;
}
}
現在の値を必要とするコンポーネントは、サービスからその値にアクセスすることができます。
sessionStorage.isLoggedIn
これが正しい方法かどうかわからない:)
const observable = of('response')
function hasValue(value: any) {
return value !== null && value !== undefined;
}
function getValue<T>(observable: Observable<T>): Promise<T> {
return observable
.pipe(
filter(hasValue),
first()
)
.toPromise();
}
const result = await getValue(observable)
// Do the logic with the result
// .................
// .................
// .................
あなたはここからそれを実装する方法に関する記事全文をチェックすることができます。 https://www.imkrish.com/how-to-get-current-value-of-observable-in-a-clean-way/
それはやり過ぎに思えるかもしれませんが、これはObservabletypeを保ち、定型文を減らすための単なる「可能な」解決策です...
Observableの現在の値を取得するために、常にextension getterを作成できます。
これを行うには、Observable<T>
タイピング宣言ファイルでglobal.d.ts
インターフェースを拡張する必要があります。次に、extension getterをobservable.extension.ts
ファイルに実装し、最後にタイピングと拡張子ファイルの両方をアプリケーションに含めます。
Angularアプリケーションに拡張子を含める方法については、この StackOverflow Answer を参照してください。
// global.d.ts
declare module 'rxjs' {
interface Observable<T> {
/**
* _Extension Method_ - Returns current value of an Observable.
* Value is retrieved using _first()_ operator to avoid the need to unsubscribe.
*/
value: Observable<T>;
}
}
// observable.extension.ts
Object.defineProperty(Observable.prototype, 'value', {
get <T>(this: Observable<T>): Observable<T> {
return this.pipe(
filter(value => value !== null && value !== undefined),
first());
},
});
// using the extension getter example
this.myObservable$.value
.subscribe(value => {
// whatever code you need...
});