RxJS如何将带条件的filter操作符移到pipe管道内map外层
问题解决
报错核心原因
- 混淆了两类
filter的作用:RxJS pipe中的filter操作符用来过滤整个Observable流的发射值,决定是否让值继续向后传递,并非用来过滤数组内部元素;你原代码中使用的是JS原生数组的filter方法,作用是过滤单个数组内的成员,两者功能完全不同。 - 类型不匹配:接口返回值是
Menu[](菜单数组类型),但你在filter中给参数标注的是Menu(单个菜单对象类型),类型对不上,同时尝试访问数组上不存在的Description属性,类型推导异常后传递到后续map就会触发报错。
正确改造方案
如果要把数组过滤逻辑移到原有map的外层,只需在外层新增一个RxJS的map操作符,在内部执行数组过滤逻辑即可:
return this.http.get<Menu[]>('profili/usermenu') .pipe( // 外层map专门处理数组过滤逻辑 map((menu: Menu[]) => { return this.appConfig.config.DisableRitiriDetails ? menu.filter(item => !item.Description.includes('xxx')) : menu; }), map((menu: Menu[]) => { const menuCreated: SidenavItem[] = this.menuSrv.populateMenu(menu); this.router.navigate([menuCreated[0].routeOrFunction]); return new MenuSuccess(menuCreated); }), catchError(() => of(new LoginError(3))) );
可选写法(不推荐)
如果确实要使用RxJS的filter操作符处理单条菜单项,需要先把数组拆分为逐个发射的独立值,过滤完成后再合并为数组,这种写法复杂度更高,无特殊需求不建议使用:
return this.http.get<Menu[]>('profili/usermenu') .pipe( // 将数组拆分为单个Menu项逐个发射 concatMap(menu => from(menu)), // 此时filter的参数为单个Menu对象,过滤逻辑生效 filter((menu: Menu) => !this.appConfig.config.DisableRitiriDetails || !menu.Description.includes('xxx')), // 过滤完成后重新合并为数组 toArray(), map((menu: Menu[]) => { const menuCreated: SidenavItem[] = this.menuSrv.populateMenu(menu); this.router.navigate([menuCreated[0].routeOrFunction]); return new MenuSuccess(menuCreated); }), catchError(() => of(new LoginError(3))) );
内容的提问来源于stack exchange,提问作者pinale
相关产品推荐
相关产品推荐

