optimize read calls

This commit is contained in:
2026-03-09 16:32:13 +01:00
parent ed69d9e972
commit 3fb2e8b341
11 changed files with 64 additions and 43 deletions

View File

@@ -1,18 +1,25 @@
import {Injectable} from '@angular/core';
import {Song} from './song';
import {BehaviorSubject, Observable} from 'rxjs';
import {Observable} from 'rxjs';
import {DbService} from '../../../services/db.service';
import {map} from 'rxjs/operators';
import {map, shareReplay, startWith} from 'rxjs/operators';
@Injectable({
providedIn: 'root',
})
export class SongDataService {
public list$ = new BehaviorSubject<Song[]>([]);
private collection = 'songs';
public list$: Observable<Song[]> = this.dbService.col$<Song>(this.collection).pipe(
startWith([] as Song[]), // immediate empty emit keeps UI responsive while first snapshot arrives
shareReplay({
bufferSize: 1,
refCount: false, // keep the listener alive after first subscription to avoid reloading on navigation
})
);
public constructor(private dbService: DbService) {
this.dbService.col$<Song>(this.collection).subscribe(_ => this.list$.next(_));
// Warm the shared stream once at startup to avoid first-navigation delay.
// this.list$.subscribe();
}
// public list$ = (): Observable<Song[]> => this.dbService.col$(this.collection);

View File

@@ -3,7 +3,7 @@ import {Injectable} from '@angular/core';
import {Observable} from 'rxjs';
import {SongService} from './song.service';
import {Song} from './song';
import {filter} from 'rxjs/operators';
import {take} from 'rxjs/operators';
@Injectable({
providedIn: 'root',
@@ -12,6 +12,6 @@ export class SongListResolver {
public constructor(private songService: SongService) {}
public resolve(): Observable<Song[]> {
return this.songService.list$().pipe(filter(_ => _.length > 0));
return this.songService.list$().pipe(take(1));
}
}

View File

@@ -26,16 +26,11 @@ import {FaIconComponent} from '@fortawesome/angular-fontawesome';
})
export class SongListComponent implements OnInit, OnDestroy {
public anyFilterActive = false;
public songs$: Observable<Song[]> | null = combineLatest([
public songs$: Observable<Song[]> = combineLatest([
this.activatedRoute.queryParams.pipe(map(_ => _ as FilterValues)),
this.activatedRoute.data.pipe(
map(data => data.songList as Song[]),
map(songs => songs.sort((a, b) => a.number - b.number))
),
this.songService.list$().pipe(map(songs => [...songs].sort((a, b) => a.number - b.number))),
]).pipe(
map(_ => {
const songs = _[1];
const filter = _[0];
map(([filter, songs]) => {
this.anyFilterActive = this.checkIfFilterActive(filter);
return songs.filter(song => this.filter(song, filter)).sort((a, b) => a.title?.localeCompare(b.title));
})

View File

@@ -5,13 +5,11 @@ import {SongListComponent} from './song-list/song-list.component';
import {EditComponent} from './song/edit/edit.component';
import {NewComponent} from './song/new/new.component';
import {EditSongGuard} from './song/edit/edit-song.guard';
import {SongListResolver} from './services/song-list.resolver';
const routes: Routes = [
{
path: '',
component: SongListComponent,
resolve: {songList: SongListResolver},
pathMatch: 'full',
},
{