Angular 14:如何在pipe中通过map筛选控球后卫子数组
问题背景
我正在重构一个Web应用,该应用展示金州勇士队的球员阵容,点击球员图片可查看NBA球员的更详细信息。
我通过Observable(roster-data.service.ts)和.subscribe()(players.component.ts)从JSON Server/JSON Placeholder获取数据,基于为每位球员创建的Player类(player.ts)进行开发,该类通过名为enumPosition.ts的枚举将球员分为五个位置,每个位置对应一个数字。
枚举定义(enumPosition.ts)
export enum Position { PointGuard = 1, ShootingGuard = 2, SmallForward = 3, PowerForward = 4, Center = 5, }
Player类(player.ts)
import { Position } from "../models/enumPosition"; export class Player { constructor( public fullName: string, public shirtNumber: string, public position: number, public height: string, public weight: number, public points: number, public rebounds: number, public assists: number, public blocks: number, public steals: number, public imageFile: string, public imageDescrip: string ) { this.fullName = fullName; this.shirtNumber = shirtNumber; this.position = position; this.height = height; this.weight = weight; this.points = points; this.rebounds = rebounds; this.assists = assists; this.blocks = blocks; this.steals = steals; this.imageFile = imageFile; this.imageDescrip = imageDescrip; } }
组件控制器(players.component.ts)
import { Component, OnInit, isDevMode } from '@angular/core'; import { RosterDataService } from "../../services/roster-data.service"; import { Player } from "../../models/player"; import { imgRoute } from "../../services/img-route.service"; @Component({ selector: 'app-players', templateUrl: './players.component.html', styleUrls: ['./players.component.scss'], providers: [RosterDataService] }) export class PlayersComponent implements OnInit { public imageLocation:string; public pointGuards!: Player[]; public shootingGuards!: Player[]; public smallForwards!: Player[]; public powerForwards!: Player[]; public centers!: Player[]; public getPlayers: Player[] = []; constructor(private _rosterDataService: RosterDataService) { this.imageLocation = imgRoute.path; } ngOnInit(): void { this.dev_SuscribeAllPointGuards(); } dev_SuscribeAllPointGuards(){ this._rosterDataService.jSON_Server_ReadPointGuards().subscribe( pointguards => { this.pointGuards = pointguards; } ); } }
服务文件(roster-data.service.ts)
import { Injectable } from '@angular/core'; import { Player } from "../models/player"; import { environment } from "../../environments/environment"; import {HttpClient, HttpErrorResponse} from '@angular/common/http'; import {Observable, throwError} from 'rxjs'; import {catchError, map, filter} from 'rxjs/operators'; import { Position } from '../models/enumPosition'; @Injectable({ providedIn: 'root' }) export class RosterDataService { private readonly devURL = environment.url; public bases!: Player[]; public escoltas!: Player[]; public aleros!: Player[]; public alaPivots!: Player[]; public pivots!: Player[]; public players!: Player[]; constructor(private http: HttpClient) { } jSON_Server_ReadPointGuards():Observable<Player[]> { return this.http.get<Player[]>(this.devURL + "/roster_GoldenStateWarriors").pipe( map((jugones:Player[]) => { jugones.find(player => player.position === 1); return jugones;}), catchError(this.handleError) ); } private handleError(err: HttpErrorResponse) { let errorMessage = ''; if (err.error instanceof ErrorEvent) { errorMessage = `An error occurred: ${err.error.message}`; } else { errorMessage = `Server returned code: ${err.status}, error message is: ${err.message}`; } console.error(errorMessage); return throwError(() => errorMessage); } }
问题
如何正确筛选出仅包含控球后卫(player.position == 1)的子数组?
解决方案
你当前代码的问题在于使用了Array.find()方法,该方法仅返回数组中第一个符合条件的元素,而非所有符合条件的元素集合。要筛选出所有控球后卫,需要替换为Array.filter()方法,该方法会返回所有满足条件的元素组成的新数组。
1. 修改现有方法
更新roster-data.service.ts中的jSON_Server_ReadPointGuards()方法:
jSON_Server_ReadPointGuards():Observable<Player[]> { return this.http.get<Player[]>(this.devURL + "/roster_GoldenStateWarriors").pipe( // 使用filter替换find,并直接引用枚举值增强可读性 map((jugones: Player[]) => jugones.filter(player => player.position === Position.PointGuard)), catchError(this.handleError) ); }
这里直接使用枚举值Position.PointGuard而非硬编码数字1,能提升代码的可维护性——如果后续枚举值有修改,无需逐个修改硬编码的数字。
2. 通用位置筛选方法(推荐)
为避免重复编写多个类似的位置筛选方法,可以封装一个通用函数,支持传入任意位置枚举值获取对应球员:
// 在RosterDataService类中添加该方法 getPlayersByPosition(position: Position): Observable<Player[]> { return this.http.get<Player[]>(this.devURL + "/roster_GoldenStateWarriors").pipe( map(players => players.filter(player => player.position === position)), catchError(this.handleError) ); }
之后在组件中调用时,只需传入对应枚举值即可:
// 在players.component.ts的dev_SuscribeAllPointGuards方法中修改 dev_SuscribeAllPointGuards(){ this._rosterDataService.getPlayersByPosition(Position.PointGuard).subscribe( pointguards => { this.pointGuards = pointguards; } ); } // 同理,获取其他位置球员也可以直接调用 // this._rosterDataService.getPlayersByPosition(Position.Center).subscribe(...);
内容的提问来源于stack exchange,提问作者Eric Díaz
相关产品推荐
相关产品推荐

