使用async管道传递Observable到input引发HTTP无限循环无返回值如何解决
问题原因
Angular的变更检测机制会在每个检测周期执行模板中绑定的方法,你的getItem方法每次被调用都会返回一个全新的Observable对象。async管道检测到传入的Observable发生变化,就会自动取消旧的订阅,订阅新的Observable,进而触发新的HTTP请求。变更检测会频繁触发,就出现了无限请求的问题。同时因为每次都是新的Observable,旧请求的返回结果会被直接丢弃,所以子组件的input接收不到有效数值。
可行解决方案
方案1:提前预加载所有关联数据
在获取到mainList列表之后,统一发起所有行对应的HTTP请求,把返回结果挂载到每个行对象的自定义属性上,模板直接绑定该属性即可,是性能最优的方案。
// 拿到mainList之后执行预加载 loadMainList() { this.yourService.getMainList().pipe( switchMap(list => { this.mainList = list; // 批量生成所有行的关联请求 const reqList = list.map(item => this.getItem(item).pipe( map(val => { item.extraValue = val; // 将请求结果挂载到行对象上 return item; }) ) ); // 可以根据需要调整并发逻辑,避免请求过多 return forkJoin(reqList); }) ).subscribe() }
模板直接绑定属性即可,不需要异步管道:
<component [input]="obj.extraValue"></component>
方案2:给请求添加缓存
新增一个缓存容器存储已经发起过的请求,同一个对象调用getItem时直接返回已有的Observable,避免重复创建,不需要修改现有模板代码。
// 定义缓存Map,key为行对象,value为对应的请求Observable private itemReqCache = new Map<any, Observable<string>>(); getItem(obj): Observable<string> { // 已有缓存直接返回 if (this.itemReqCache.has(obj)) { return this.itemReqCache.get(obj); } const req = this.http.get('/someServiceurl').pipe( map(res => res.element), shareReplay(1) // 共享请求结果,避免多订阅重复发起请求 ); this.itemReqCache.set(obj, req); return req; } // 列表刷新/翻页时记得清空缓存,避免数据过时 refreshList() { this.itemReqCache.clear(); // 后续执行列表加载逻辑 }
方案3:把请求逻辑放到子组件内部
将异步请求逻辑封装到子组件中,父组件只需要把行对象传给子组件,由子组件自己管理请求和订阅,父层逻辑更清爽,适合子组件复用度高的场景。
子组件代码示例:
// 子组件内部 @Input() obj: any; displayValue: string; ngOnInit() { this.http.get('/someServiceurl').pipe( map(res => res.element) ).subscribe(val => { this.displayValue = val; // 后续子组件直接使用displayValue渲染即可 }) }
父组件模板写法:
<component [obj]="obj"></component>
内容的提问来源于stack exchange,提问作者Programmer
相关产品推荐
相关产品推荐

