Angular+Firestore如何按匹配属性将查询结果推入指定数组
优化方案
原有实现的问题
- 变量引用错误:
updateArray方法中判断条件用了未定义的item变量,实际应该是循环的album参数 - 性能冗余:每遍历一张专辑就全局搜索一次艺人数组,当艺人/专辑数据量较大时,时间复杂度会升到O(n*m)
- 变量污染:用了组件全局的
this.albums存储专辑,如果有多个组件二实例同时存在,会出现不同艺人的专辑互相覆盖的问题 - 边界缺失:没有判断目标艺人是否存在、也没有初始化
albums字段,遇到空值会直接报错
适配当前场景的最优实现
你当前的组件二已经通过@Input拿到了对应艺人的ID,完全不需要遍历所有专辑再逐个匹配艺人,直接定位目标艺人插入数据即可,性能更高逻辑也更清晰:
@Input() artist_id: string; ngOnInit(): void { this.albums$ = this.service .getAlbums$(var1, var2, etc) .pipe( filter(Boolean), // 等价于原来的filter(data => !!data),写法更简洁 take(1), tap(albums => this.mergeAlbumsToArtist(albums)) ); } private mergeAlbumsToArtist(albums: any[]): void { // 直接定位当前组件对应的艺人,只遍历一次艺人数组 const targetArtist = this.service.myArray['artists'].find(artist => artist.id === this.artist_id); // 边界判断,避免空值报错 if (!targetArtist) return; // 初始化albums字段,避免第一次插入时报未定义错误 if (!Array.isArray(targetArtist.albums)) targetArtist.albums = []; // 批量推入当前查询到的所有专辑 targetArtist.albums.push(...albums); }
批量组装全量专辑的场景(可选)
如果你后续改成一次性查询所有艺人的所有专辑,再批量组装到myArray中,可以用Map做索引把查找复杂度降到O(1):
private mergeAllAlbums(albums: any[]): void { // 先把艺人数组转成ID为key的Map,后续查找不用遍历 const artistMap = new Map( this.service.myArray['artists'].map(artist => [artist.id, artist]) ); albums.forEach(album => { const targetArtist = artistMap.get(album.artist_id); if (!targetArtist) return; if (!Array.isArray(targetArtist.albums)) targetArtist.albums = []; targetArtist.albums.push(album); }); }
额外注意点
如果你用了Angular的OnPush变更检测策略,直接修改Service里的普通数组不会触发视图更新,建议把myArray改成BehaviorSubject类型的可观察对象,修改后调用next方法通知订阅方更新视图。如果需要避免重复插入相同专辑,可以在push前加个ID去重判断即可。
内容的提问来源于stack exchange,提问作者user8836786
相关产品推荐
相关产品推荐

