为何CombineLatest会修改原Observable?Angular搜索流异常
问题原因与解决方案
为什么原始的ally$数据会被修改?
这和CombineLatest没关系,纯粹是JavaScript对象的引用特性导致的:
ally$发出的UserAndMatch是引用类型的对象,你在allyFilter里直接执行ally.users = ally.users.filter(...),等于直接修改了原始对象的users属性——因为变量ally指向的就是ally$缓存对象的内存地址,改它就是改原始数据。- 加上你用了
shareReplay(1),这个操作符会缓存ally$的最新值,后续每次CombineLatest拿到的都是被修改过的对象,自然删除搜索字符后没法恢复原始数组。
解决方法:不修改原始对象,返回新对象
核心思路是:过滤时创建一个新的UserAndMatch对象,复制原始对象的所有属性,只替换过滤后的users数组,完全不碰原始数据。
修改后的代码示例
- 修复
allyFilter方法:
allyFilter(ally: UserAndMatch, query: string): UserAndMatch { // 浅拷贝原对象,仅替换users属性,不修改原始数据 return { ...ally, users: ally.users.filter(user => user.name.toLowerCase().includes(query)) }; }
额外优化:把
user.name转成小写,和query的处理逻辑一致,避免大小写不匹配导致的搜索失效。
- 顺带修复原代码里的语法错误(
switchMap后缺括号):
ally$: Observable<UserAndMatch> = this.user$.pipe( switchMap((user: User) => this.userService.getFollowing(user)), shareReplay(1), );
这样每次过滤都会生成全新的UserAndMatch对象,ally$缓存的原始数据完全不受影响,删除搜索字符时,CombineLatest能拿到完整的原始users数组,重新生成全量结果。
内容的提问来源于stack exchange,提问作者Igor Cantele
相关产品推荐
相关产品推荐

