I have a js class that has a BehaviorSubject and an Observable. I want to subsribe to the Observable in a different class, which does not work, properly.
//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
}
}
So My main questions: How can I make sure that the subscriber gets all the changes in ClassTwo?
Note that the Observable is defined and fires once, but is not notified with new changes.
Does it make a difference when ClassOne is a Singleton?:
//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
}
Edit: Test if its a singleton (using jest)
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);
});
Edit2: Use of Add data
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);
Edit3: Using share/shareReplay
I have changed the getStore() function:
//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)})
But the Problem remains.
Edit4: Some Trouble shooting
So after some testing and reading I come to the conclusion that subscriptions in constructors are not working properly.
While this is not working:
let two = new ClassTwo(); //with the subscription on the store
This works:
let two = new ClassTwo(); //without the subscription on the store
two.subscribeToMyStore();
//subscribeToMyStore:
subscribeToMyStore(){
this.one.store.subscribe(data =>{console.log(data)})
}
So why cant I do subscriptions in the constructor?
And why would it subscribe in the constructor of ClassOne but not ClassTwo?
You have to reuse the same instance. Either ensure it is singleton and inject in through the constructor using some DI framework, or export singleton yourself from separate moudle and don't forget to share it. Note that there exist quite popular scenarios when shareReplay is needed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With