Angular 2 Observable问题:如何在应用生命周期内持久存储玩家数据?
Hey there! Let's figure out what's going on with your Angular Observable issue and how to keep that player data around for your app's entire lifecycle.
First, let's tackle the "only seeing 1 player data" bug. From what you described, the subscription is pushing data to your array correctly, but when you try to return it in an if statement, only one shows up. Chances are, your local component array is getting reset when the component is destroyed (like when you switch routes). Components are created and destroyed as you navigate, so any data stored directly in a component variable will be lost when you leave that component.
Now, for the solution: we need to store your player data in a singleton service (Angular services provided in root are singletons by default) so it persists across route changes and component lifecycles. Even better, using an RxJS BehaviorSubject will let components subscribe to the latest data automatically, and we can add local storage if you need data to survive page refreshes too.
Step 1: Update Your Player Service
Modify your service to use a BehaviorSubject to hold the player data, and add logic to sync with local storage if needed:
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { BehaviorSubject, Observable } from 'rxjs'; import { tap } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class PlayerService { // BehaviorSubject holds the current state of players, starts empty private _players = new BehaviorSubject<any[]>([]); // Expose an observable so components can subscribe (can't modify directly) public players$ = this._players.asObservable(); constructor(private http: HttpClient) { // Load saved players from local storage when the service initializes this.loadSavedPlayers(); } fetchPlayers(): Observable<any[]> { return this.http.get<any[]>('your-player-api-endpoint').pipe( tap(newPlayers => { // Merge new players with existing ones (add duplicate checks if needed) const updatedPlayers = [...this._players.value, ...newPlayers]; // Update the BehaviorSubject with the new data this._players.next(updatedPlayers); // Save to local storage for page refresh persistence localStorage.setItem('savedPlayers', JSON.stringify(updatedPlayers)); }) ); } private loadSavedPlayers(): void { const saved = localStorage.getItem('savedPlayers'); if (saved) { this._players.next(JSON.parse(saved)); } } // Optional: Get the current player data synchronously if needed getCurrentPlayers(): any[] { return this._players.value; } }
Step 2: Update Your Component
Now your component will subscribe to the service's observable instead of managing its own array. This way, even if the component is destroyed and recreated (like after a route switch), it'll immediately get the latest player data from the service:
import { Component, OnInit } from '@angular/core'; import { PlayerService } from './player.service'; @Component({ selector: 'app-player-list', templateUrl: './player-list.component.html' }) export class PlayerListComponent implements OnInit { players: any[] = []; constructor(private playerService: PlayerService) {} ngOnInit(): void { // Subscribe to the service's player data stream this.playerService.players$.subscribe(players => { this.players = players; console.log('All players:', this.players); // You should see all 3 here now }); // Only fetch players if we don't already have them if (this.playerService.getCurrentPlayers().length === 0) { this.playerService.fetchPlayers().subscribe(); } } // If your if statement was returning filtered data, use the service's current data getFilteredPlayers() { // Example: Return players that meet a specific condition return this.players.filter(player => /* your condition here */); } }
Why This Fixes Your Issues
- No more lost data on route changes: The service is a singleton, so its
_playersBehaviorSubject retains data even when components are destroyed. - Consistent data across components: Any component that injects
PlayerServicecan subscribe toplayers$and get the latest data instantly. - Page refresh persistence: The local storage sync ensures your player data stays around even if the user refreshes the browser.
If your original "only 1 player" bug was happening because you were reinitializing the component's array on every load, this approach eliminates that problem entirely—since the source of truth is now the service, not the component.
内容的提问来源于stack exchange,提问作者NoLimes

