I'd like to access the Observable's value coming from a Service in two different components.
This is how I'm trying to do it:
// My service holding on Observable and initialising it with a value of 1,
// then resetData() creates a new Observable with a value of 0.
@Injectable({
providedIn: 'root',
})
export class DataService {
data$;
constructor() {
this.data$ = of(1);
}
getData() {
return this.data$;
}
resetData() {
this.data$ = of(0);
}
}
Then I try to call resetData()
in cmp1
Component but the new value is not there.
@Component()
class cmp1 implements OnInit {
data$: Observable<number>;
data: number;
constructor(private dataService: DataService) {}
ngOnInit() {
this.data$ = this.dataService.getData();
this.data$.subscribe((value) => (this.data = value));
console.log(this.data); // should be 1
}
doStuff() {
this.dataService.resetData();
console.log(this.data); // should be 0
}
}
I also try to access that same value in a different component and the value is also not there:
@Component()
class cmp2 implements OnInit {
data$: Observable<number>;
data: number;
constructor(private dataService: DataService) {}
ngOnInit() {
this.data$ = this.dataService.getData();
this.data$.subscribe((value) => (this.data = value));
console.log(this.data); // should be 1
}
doStuff() {
this.dataService.resetData();
console.log(this.data); // should be 0
}
}
There are two questions here to answer this fully:
- How to access a value of the Observable coming from a Service in a Component?
- How to access a value of the Observable coming from a Service in two different Components?
CodePudding user response:
I'm assuming that the subscription's first value is firing, ie you're writing 1 to the console? And the problem is that you don't get any more updates after calling resetData()
? If so, that is due to you re-initializing the Observable
. You're overwriting it basically, making any previous subscriptions obsolete.
What your method could do, is something like
resetData(): void {
this.data$.next(0);
}
CodePudding user response:
You should take the time to learn more about Observables because it is a required knowledge and should be well understood. There is plenty of resources about them.
Firstly, a common mistake is to think values will be available out ouf the subscription:
this.dataService.resetData();
console.log(this.data); // should be 0
If the observable needs few seconds to send the result then this.data will still have the old value when you log it.
You should log new values inside the subscription:
this.data$.subscribe((value: number) => {
this.data = value;
console.log(this.data);
});
Also, as @Aldin Bradaric answered, when you do:
this.data$ = of(0);
then you create a new object but your components still have subscriptions to the old one.
About your needs, you should use Subjects rather than Observables: have a look to What is the difference between Observable and a Subject in rxjs?)
Then your service will be like:
export class DataService {
data$: Subject<number> = new ReplaySubject();
constructor() {
this.data$.next(1);
}
getData() {
return this.data$;
}
resetData() {
setTimeout(() => {
this.data$.next(0);
}, 1000)
}
}