是否有一个等效的 BehaviorSubject 不需要初始值并且能够提供当前值?



寻找与BehaviorSubject相同的功能,但无需提供初始值。

我经常需要订阅一个主题,然后才能从我加载数据的任何来源加载数据。当且仅当next()先前在主题上被调用时,我还需要订阅在订阅后立即触发,并且我希望它向我显示最后发出的值,以及能够在任何时间点同步获得当前值,类似于BehaviorSubjectvalue字段。

这是我尝试的:

  • 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()函数。

最新更新