寻找与BehaviorSubject
相同的功能,但无需提供初始值。
我经常需要订阅一个主题,然后才能从我加载数据的任何来源加载数据。当且仅当next()
先前在主题上被调用时,我还需要订阅在订阅后立即触发,并且我希望它向我显示最后发出的值,以及能够在任何时间点同步获得当前值,类似于BehaviorSubject
的value
字段。
这是我尝试的:
Subject
,但是它不像BehaviorSubject
那样在订阅后立即发出旧值,并且我无法检索当前值。ReplaySubject
的缓冲区大小为1,但这也不允许检索当前值BehaviorSubject.create()
而不是new BehaviorSubject<Whatever>(null)
,但在调用next()
时这只是不做任何事情。不发出任何值,并且订阅代码永远不会触发。BehaviorSubject
与.pipe(skip(1)).subscribe
,但如果我在调用next()
后运行此代码,那么我将失去旧的但有效的值,仅在再次调用next
后触发。
我想到的唯一解决方案是扩展ReplaySubject
类,为当前值添加一个私有字段,该字段在调用next()
时设置,并添加一个getter来检索它。
我总是期望这些值被定义和有效,所以我不明白为什么我必须为一个对象类型提供一个默认的null/undefined值给BehaviourSubject
,我特别希望不是undefined/null,并相应地显式定义它们,然后在每个订阅中写一个if语句来检查每次发出一个新值是否有效。
我也不明白为什么每次我在加载数据之前订阅主题时,它都必须发出空值,并且毫无理由地导致每次订阅被触发。
那么我还错过了其他的选择吗?
编辑:到目前为止,我的问题的答案似乎是没有,没有等价物。因此,我为任何寻找相同行为的人提供了我的工作:import { ReplaySubject } from 'rxjs';
export class SensibleSubject<T>
{
private replaySubject: ReplaySubject<T>;
private _canGetValue = false;
private _value!: T;
public get value()
{
if (!this._canGetValue)
throw new Error("Attempted to retrieve value before it has been set!");
return this._value;
}
constructor()
{
this.replaySubject = new ReplaySubject<T>(1);
}
public next(value: T)
{
this._canGetValue = true;
this._value = value;
this.replaySubject.next(value);
}
public asObservable()
{
return this.replaySubject.asObservable();
}
public canGetValue()
{
return this._canGetValue;
}
}
最初,我指定我扩展了ReplaySubject
类,但是,正如crowmagnumb在他对行为主题初始值null的回答中指出的那样?在ReplaySubject
上重写next
会以某种方式破坏它。相反,我决定包装ReplaySubject
并公开所需的方法和字段。
src = new BehaviorSubject<any>(null);
obs$ = src.asObservable.pipe(filter(value => !!value));
既然您说发送到源的所有值都是有效的,而不是undefined
,那么filter
管道将只过滤初始默认的null
。这样,您就不必在每个订阅中进行if
检查,并且仍然可以保持同步的getValue()
函数。