Files
NowChess-Frontend/src/app/services/game-stream.service.ts
T
2026-04-22 08:28:16 +02:00

64 lines
1.8 KiB
TypeScript

import { Injectable, DestroyRef, inject } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { interval, startWith, Subscription, switchMap } from 'rxjs';
import { GameApiService } from './game-api.service';
import { GameStreamEvent } from '../models/game.models';
@Injectable({ providedIn: 'root' })
export class GameStreamService {
private readonly gameApi = inject(GameApiService);
private readonly destroyRef = inject(DestroyRef);
private streamSubscription: Subscription | null = null;
private pollSubscription: Subscription | null = null;
startStreaming(
gameId: string,
onEvent: (event: GameStreamEvent) => void,
onStreamError: () => void
): void {
this.streamSubscription = this.gameApi
.streamGame(gameId)
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe({
next: (event) => onEvent(event),
error: () => {
onStreamError();
this.startPolling(gameId, onEvent);
},
complete: () => {
onStreamError();
this.startPolling(gameId, onEvent);
}
});
}
startPolling(gameId: string, onEvent: (event: GameStreamEvent) => void): void {
if (this.pollSubscription) {
return;
}
this.pollSubscription = interval(1500)
.pipe(
startWith(0),
switchMap(() => this.gameApi.getGame(gameId)),
takeUntilDestroyed(this.destroyRef)
)
.subscribe({
next: (game) => {
const event: GameStreamEvent = {
type: 'gameFull',
game
};
onEvent(event);
}
});
}
cleanup(): void {
this.streamSubscription?.unsubscribe();
this.pollSubscription?.unsubscribe();
this.streamSubscription = null;
this.pollSubscription = null;
}
}