I have database queries that get executed and return data from the server. When the data returns my subscription works. If I call refreshData the queries execute again and return data, however the subscription in AnotherComponent doesn't run the second time.
I believe that this is caused by take(1) which is taking one item and ending the subscription. Is there a way that I can end the interval, but keep the subscription active in AnotherComponent?
Note: I decided to use an interval because some items subscribe too late and never receive the initial data.
I don't think that a ReplaySubject is the way to go because I don't care what the previous data was.
This service makes the applications initial queries needed to load a page.
export class StartupGraphqlService {
private initCalled = false;
private queryResults?: StartupCompletion;
private readonly startupQueries = new Subject<StartupCompletion>();
get $startupQueries() {
return interval(100)
.pipe(
filter(() => !!this.queryResults),
map(() => this.queryResults as StartupCompletion),
take(1)
);
}
refreshData() {
this.initCalled = false;
this.initQueries();
}
initQueries() {
if (this.initCalled) return;
this.initCalled = true;
// Execute queries
// ...
this.startupQueries.next(data)
}
}
This component executes the initial query then 3 seconds later (for testing) executes it again.
export class AppComponent {
ngOnInit() {
this.authService.loggedIn().subscribe(logged => {
if(logged) {
this.startupQueries.initQueries();
timer(3000).subscribe(() => {
console.log('Refresh Queries');
this.startupQueries.refreshData();
});
}
}
}
}
This should display the result every time it is updated.
export class AnotherComponent {
ngOnInit() {
this.startup.$startupQueries.subscribe(result => {
console.log(result);
})
}
}
I found that using a BehaviorSubject works, it seems to be doing what I intended.
private queryResults?: StartupCompletion;
private readonly startupQueries = new BehaviorSubject<StartupCompletion | undefined>(this.queryResults);
$startupQueries = this.startupQueries.asObservable().pipe(
filter(() => !!this.queryResults),
map(() => this.queryResults as StartupCompletion),
);