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의 현재 값을 가져와야합니다. 어떻게해야합니까?
답변
A Subject
또는 Observable
현재 값이 없습니다. 값이 방출되면 구독자에게 전달되고 값 Observable
이 완료됩니다.
현재 값을 원한다면 BehaviorSubject
정확히 그 목적을 위해 설계된 값을 사용하십시오 . BehaviorSubject
마지막으로 방출 된 값을 유지하고 새로운 가입자에게 즉시 방출합니다.
getValue()
현재 값을 얻는 방법도 있습니다 .
답변
당신이 유일한 방법 해야한다 “에서”값을 얻지는 관찰 가능한 / 주제 구독 함께!
당신이 사용 getValue()
하고 있다면 선언적 패러다임에서 명령적인 일을하고있는 것입니다. 탈출구로 있지만 99.9 %는 사용하지 않아야합니다 getValue()
. 몇 가지 흥미로운 일 getValue()
이 있습니다. 주체가 구독을 취소하면 오류가 발생하고 오류로 인해 주제가 죽은 경우 값을 얻지 못하게됩니다. 그러나 다시, 탈출로 드문 상황에 부화.
“Rx-y”방식으로 Subject 또는 Observable에서 최신 값을 얻는 방법에는 여러 가지가 있습니다.
- 사용
BehaviorSubject
: 그러나 실제로 구독 . 처음 구독BehaviorSubject
하면 수신하거나 초기화 한 이전 값을 동 기적으로 전송합니다. - Using a
ReplaySubject(N)
:N
값 을 캐시 하고 새 구독자에게 재생합니다. A.withLatestFrom(B)
:이 연산자를 사용하여 관찰B
가능A
방출 시 관찰 가능 값에서 최신 값을 가져옵니다 . 배열의 두 값을 모두 제공합니다[a, b]
.A.combineLatest(B)
: 사용이 연산자는 가장 최근의 값을 얻을A
하고B
때마다 하나A
또는B
방출한다. 배열의 두 값을 모두 제공합니다.shareReplay()
:를 통해 Observable 멀티 캐스트를 작성ReplaySubject
하지만 오류가 발생하면 Observable을 재 시도 할 수 있습니다. 기본적으로 캐쉬 동작을 약속합니다.publishReplay()
,publishBehavior(initialValue)
,multicast(subject: BehaviorSubject | ReplaySubject)
, 등 : 다른 사업자를 활용BehaviorSubject
하고ReplaySubject
. 같은 것의 다른 풍미, 그들은 기본적으로 주제를 통해 모든 알림을 깔아서 관찰 가능한 소스를 멀티 캐스트합니다.connect()
제목으로 소스를 구독 하려면 전화해야합니다 .
답변
나는 늦은 구독자가 그 가치에 도달 한 후 주제를 구독하는 비슷한 상황이 있었다.
이 경우 BehaviorSubject와 비슷한 ReplaySubject 가 매력처럼 작동 한다는 것을 알았 습니다 . 더 나은 설명으로 연결되는 링크는 다음과 같습니다. http://reactivex.io/rxjs/manual/overview.html#replaysubject
답변
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/
답변
하위 구성 요소에서 처음에 주제의 현재 값을 가져야하는 동일한 문제가 발생 한 다음 주제를 구독하여 변경 사항을 듣습니다. 구성 요소가 다음과 같이 액세스 할 수 있도록 서비스의 현재 값을 유지합니다.
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
이것이 올바른 습관인지 확실하지 않습니다 🙂
답변
비슷한 찾고 대답을 downvoted했다. 그러나 제한된 경우에 대해 내가 제안하는 것을 정당화 할 수 있다고 생각합니다.
관찰 가능 항목에 현재 값 이없는 것이 사실이지만 , 종종 즉시 사용 가능한 값을 갖습니다. 예를 들어 redux / flux / akita 상점의 경우 여러 관측 가능 항목을 기반으로 중앙 상점에 데이터를 요청할 수 있으며 일반적으로 해당 값을 즉시 사용할 수 있습니다.
이 경우이면 subscribe
값이 즉시 돌아옵니다.
그럼 당신이 서비스에 전화를했다 말, 및 완료에 당신이 상점에서 무언가의 최신 값을 싶어 할 가능성이 방출되지 않을 수도 있음 :
당신은 이것을 시도 할 수 있습니다 (그리고 가능한 한 많은 것을 파이프 안에 보관해야합니다) :
serviceCallResponse$.pipe(withLatestFrom(store$.select(x => x.customer)))
.subscribe(([ serviceCallResponse, customer] => {
// we have serviceCallResponse and customer
});
이것의 문제는 2 차 관측 가능 값이 방출 될 때까지 차단 될 수 있다는 것입니다.
나는 최근 에 값을 즉시 사용할 수있는 경우에만 관측 가능 항목을 평가해야한다는 것을 알았 으며, 더 중요하게는 그렇지 않은 경우를 감지 할 수 있어야했습니다. 나는 이것을 끝내었다.
serviceCallResponse$.pipe()
.subscribe(serviceCallResponse => {
// immediately try to subscribe to get the 'available' value
// note: immediately unsubscribe afterward to 'cancel' if needed
let customer = undefined;
// whatever the secondary observable is
const secondary$ = store$.select(x => x.customer);
// subscribe to it, and assign to closure scope
sub = secondary$.pipe(take(1)).subscribe(_customer => customer = _customer);
sub.unsubscribe();
// if there's a delay or customer isn't available the value won't have been set before we get here
if (customer === undefined)
{
// handle, or ignore as needed
return throwError('Customer was not immediately available');
}
});
위의 모든 subscribe
것에서 나는 @Ben이 논의한 것처럼 값을 얻는 데 사용 하고 있습니다. .value
내가있는 경우에도 속성을 사용하지 않습니다 BehaviorSubject
.
답변
과잉으로 들릴 수도 있지만 이것은 Observable 유형 을 유지 하고 상용구를 줄이는 또 다른 “가능한”솔루션입니다 …
Observable의 현재 값을 얻기 위해 항상 확장 getter 를 작성할 수 있습니다 .
이렇게하려면 타이핑 선언 파일 Observable<T>
에서 인터페이스 를 확장해야 global.d.ts
합니다. 그런 다음 파일에 확장 getter 를 구현 observable.extension.ts
하고 마지막으로 입력과 확장 파일을 모두 애플리케이션에 포함하십시오.
이 StackOverflow 응답 을 참조 하여 확장을 Angular 응용 프로그램에 포함시키는 방법을 알 수 있습니다 .
// 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...
});