Javascript 如何获取RxJS主体或可观察对象的当前值?
我有一个角度2服务:Javascript 如何获取RxJS主体或可观察对象的当前值?,javascript,angular,rxjs,Javascript,Angular,Rxjs,我有一个角度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>();
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);
});
}
}
从“/Storage”导入{Storage};
从'angular2/core'导入{Injectable};
从'rxjs/Subject'导入{Subject};
@可注射()
导出类会话存储扩展了存储{
private _isLoggedInSource=新主题();
isLoggedIn=这个。_isLoggedInSource.asObservable();
构造函数(){
超级(“会话”);
}
setIsLoggedIn(值:布尔值){
此.setItem(''isLoggedIn',值,()=>{
this._isLoggedInSource.next(值);
});
}
}
一切都很好。但我有另一个不需要订阅的组件,它只需要在某个时间点获取isLoggedIn的当前值。我如何才能做到这一点?A
主题
或可观察
没有当前值。当一个值被发出时,它被传递给订阅者,并且用它来完成可观察的
如果要获得当前值,请使用专门为此目的设计的BehaviorSubject
BehaviorSubject
保留最后发出的值,并立即将其发送给新订户
它还有一个方法
getValue()
来获取当前值。我也遇到过类似的情况,即晚订户在主题值到达后订阅该主题
我发现,在这种情况下,与行为主体类似的行为主体就像一个符咒。
这里有一个更好的解释链接:你应该“从”一个可观察/主题中获得价值的唯一方法是订阅!
如果您使用的是getValue()
,那么您在声明性范例中执行的是命令式的操作。它是一个逃生舱,但是99.9%的时候你不应该使用getValue()
有一些有趣的事情getValue()
会做:如果主题被取消订阅,它会抛出一个错误,如果主题因为出错而死亡,它会阻止你获得一个值,等等,这是一个特殊情况下的逃生舱
有几种方法可以通过“Rx-y”方式从受试者或可观察对象处获取最新值:
BehaviorSubject
:但实际订阅它。当您首次订阅BehaviorSubject
时,它将同步发送以前接收到或初始化的值ReplaySubject(N)
:这将缓存N
值并将其重播给新订阅者A.withLatestFrom(B)
:当可观测A
发出时,使用此运算符从可观测B
获取最新值。将在数组中为您提供两个值[a,b]
A.combinelatetest(B)
:每次A
或B
发出时,使用此运算符从A
和B
获取最新值。将在数组中为您提供两个值shareReplay()
:通过ReplaySubject
创建可观察的多播,但允许您在出现错误时重试可观察的多播。(基本上,它提供了promise-y缓存行为)publishReplay()
,publishBehavior(initialValue)
,多播(主题:BehaviorSubject | ReplaySubject)
,等等:利用BehaviorSubject
和ReplaySubject
的其他操作符。同一事物的不同风格,它们基本上通过将所有通知汇集到一个主题来多播可观察到的源。您需要调用connect()
以订阅带有主题的源代码我在子组件中遇到了同样的问题,最初它必须具有主题的当前值,然后订阅主题以侦听更改。我只是维护服务中的当前值,以便组件可以访问,例如:
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;
}
}
不确定这是否是正确的做法:)您可以将上次发出的值与可观察值分开存储。然后在需要的时候阅读
let lastValue: number;
const subscription = new Service().start();
subscription
.subscribe((data) => {
lastValue = data;
}
);
一个相似的答案被否决了。但我认为我可以证明我在有限情况下的建议
虽然一个可观察对象确实没有一个当前值,但通常它会有一个立即可用的值。例如,对于redux/flux/akita存储,您可以基于大量可观测数据从中央存储请求数据,该值通常会立即可用 如果是这种情况,则当您订阅时,该值将立即返回 假设您有一个对服务的调用,并且在完成时您希望从您的商店中获取某些可能不会发出的最新值: 您可以尝试这样做(并且您应该尽可能将东西“放在管道内”): 问题是它会一直阻塞,直到第二个可观察对象发出一个值,而这个值可能永远不会出现 我发现自己最近需要评估一个可观察的,只有当一个值立即可用时才进行评估,更重要的是,我需要能够检测到它是否可用。我最终做了这样的事:
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
属性,即使我有行为主体
const observable=of('response'))
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
// .................
// .................
// .................
函数hasValue(值:任意){
返回值!==null&&value!==未定义;
}
函数getValue(可观察:可观察):承诺{
可观测回波
.烟斗(
过滤器(hasValue),
第一()
)
.toPromise();
}
常量结果=等待获取值(可观察)
//对结果进行逻辑分析
// .................
// .................
// .................
您可以在这里查看关于如何实现它的完整文章。
虽然听起来有些过分,但这只是另一个“po”
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');
}
});
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
// .................
// .................
// .................
var sub = new rxjs.BehaviorSubject([0, 1])
sub.next([2, 3])
setTimeout(() => {sub.next([4, 5])}, 1500)
sub.subscribe(a => console.log(a)) //2, 3 (current value) -> wait 2 sec -> 4, 5
ngOnInit() {
...
// If loading with previously saved value
if (this.controlValue) {
// Take says once you have 1, then close the subscription
this.selectList.pipe(take(1)).subscribe(x => {
let opt = x.find(y => y.value === this.controlValue);
this.updateValue(opt);
});
}
}