我有一个 js 类,它有一个 BehaviorSubject 和一个 Observable。我想订阅另一个类中的 Observable,该类无法正常工作。
//class One:
export default ClassOne {
constructor(){
this._store = new BehaviorSubject({});
this.store = this._store.asObservable();
this.store.subscribe(data => {console.log(data)}) //logs the data, no Problem here
//{};{ test: { foo: "bar", max: "muster" } };{ test: { foo: "bar", max: "muster" } };...
}
addData(data){ this._store.next(data)} //iscalled a few times.
getStore () {return this.store} //using a getter Function does not work either
}
//class Two
import class1 from "./class1";
ClassTwo {
constructor(){
this.one = new ClassOne();
this.one.store.subscribe(data =>{console.log(data)}) //only logs {} once. Is never fired again.
this.one.getStore().subscribe(data =>{console.log(data)}) //Same Problem
}
}
Run Code Online (Sandbox Code Playgroud)
所以我的主要问题是:如何确保订阅者获得 ClassTwo 中的所有更改?
请注意, Observable 已定义并触发一次,但不会收到新更改的通知。
当 ClassOne 是单例时,它会有所不同吗?:
//class One:
instance = null;
export default ClassOne {
constructor(){
if (instance === null) {
instance = this;
}
instance._store = new BehaviorSubject({});
instance.store = this._store.asObservable();
instance.store.subscribe(data => {console.log(data)}) //logs the data, no Problem here
}
addData(data){ instance._store.next(data)} //iscalled a few times.
getStore () {return instance.store} //using a getter Function does not work either
}
Run Code Online (Sandbox Code Playgroud)
编辑:测试它是否是单例 (使用开玩笑)
beforeAll(() => {
one = new ClassOne();
});
test("Singleton Test", () => {
let one2 = new ClassOne();
expect(one2 instanceof ClassOne).toEqual(true);
expect(one2).toEqual(one);
expect(one2 === one).toEqual(true);
});
Run Code Online (Sandbox Code Playgroud)
Edit2:使用添加数据
beforeAll(() => {
one = new ClassOne();
two = new ClassTwo();
});
test("", (done) => {
one.addData({ test: { foo: "bar", max: "muster" } });
one.addData({ test: { foo: "bar", max: "muster" } });
one.addData({ test: { foo: "bar", max: "muster" } });
//I just coded this by heart, but the test is somthing like this
expect(one.getStore()).toEqual(two.one.store);
//makes sure that the subscriber have enough time
setTimeout(() => done(), 5000);
}, 6000);
Run Code Online (Sandbox Code Playgroud)
Edit3:使用共享/共享重播
我已经更改了 getStore() 函数:
//ClassOne
getStore(){ return instance.store.pipe(share()) }
//and I tried:
getStore(){ return instance.store.pipe(shareReplay()) }
//ClassTwo:
this.one.getStore().subscribe(data =>{console.log(data)})
Run Code Online (Sandbox Code Playgroud)
但问题仍然存在。
Edit4:一些故障排除
因此,经过一些测试和阅读后,我得出结论,构造函数中的订阅无法正常工作。
虽然这不起作用:
let two = new ClassTwo(); //with the subscription on the store
Run Code Online (Sandbox Code Playgroud)
这有效:
let two = new ClassTwo(); //without the subscription on the store
two.subscribeToMyStore();
//subscribeToMyStore:
subscribeToMyStore(){
this.one.store.subscribe(data =>{console.log(data)})
}
Run Code Online (Sandbox Code Playgroud)
那么为什么我不能在构造函数中进行订阅呢?
为什么它会订阅 ClassOne 而不是 ClassTwo 的构造函数?
所以问题在于 Jest 的速度。Jest 在执行 classTwo 订阅中的日志之前完成并清理了所有内容。
虽然很奇怪,但对我有用的解决方法是在我的测试中触发complete事件,并且只在complete回调中调用done()。看起来像这样:
beforeAll(() => {
one = new ClassOne();
two = new ClassTwo(); //subcription in constructor
});
test("", (done) => {
one.addData({ test: { foo: "bar", max: "muster" } });
one.addData({ test: { foo: "bar", max: "muster" } });
one.addData({ test: { foo: "bar", max: "muster" } });
//I just coded this by heart, but the test is something like this
two.one.store.subscribe({
complete() {
//Test the final state of everything here
//Only call done() here.
done();
},
});
setTimeout(
() => one.store.complete(), //call complete after a timeout
1000
);
}, 2000);
Run Code Online (Sandbox Code Playgroud)
所以我的要点是:
| 归档时间: |
|
| 查看次数: |
86 次 |
| 最近记录: |