多次调用API并存储结果异常:仅返回首组数据且API未多次执行
问题分析与解决方案
核心问题
- 循环逻辑失效:你一开始就基于
this.totalPages的初始值执行循环,但真实的总页数是在第一个API响应返回后才更新的。此时循环已经执行完毕,后续页码的API请求根本不会触发。 - 异步处理混乱:直接在循环内订阅多个Observable,会导致请求无序触发,且每次调用
programResults$.next()仅推送当前页数据,无法累积所有结果,还可能引发竞态问题。
解决方案
方案一:先获取总页数,并行请求所有页
如果API允许并行请求,这种方式效率更高:
import { forkJoin, map, switchMap } from 'rxjs'; public getProgramNamesList() { // 先请求第一页获取总页数 return this.accountAdminApiService.getAccountAdminProgramsBySearch(0).pipe( map(firstPage => { const totalPages = Math.ceil(firstPage.totalCount / this.pageSize); // 生成所有页码的请求数组 const pageRequests = []; for (let page = 0; page < totalPages; page++) { pageRequests.push(this.accountAdminApiService.getAccountAdminProgramsBySearch(page)); } return pageRequests; }), // 并行发起所有页的请求 switchMap(requests => forkJoin(requests)), // 合并所有页的数据为一个数组 map(allPages => allPages.flatMap(page => page.data || [])) ); }
方案二:递归请求直到所有页(适合初始未知总页数的场景)
用RxJS的expand操作符递归请求,直到没有更多数据:
import { expand, reduce, EMPTY } from 'rxjs'; public getProgramNamesList() { let currentPage = 0; return this.accountAdminApiService.getAccountAdminProgramsBySearch(currentPage).pipe( // 递归发起下一页请求,直到当前页超过总页数 expand(page => { currentPage++; const totalPages = Math.ceil(page.totalCount / this.pageSize); return currentPage < totalPages ? this.accountAdminApiService.getAccountAdminProgramsBySearch(currentPage) : EMPTY; }), // 累积所有页的数据 reduce((accumulator, page) => [...accumulator, ...(page.data || [])], []) ); }
使用说明
- 两种方案都直接返回Observable,调用方只需订阅即可获取所有合并后的数据,无需手动维护Subject。
- 如果必须使用Subject推送数据,可以在订阅上述Observable后,调用
this.programResults$.next(mergedData)。
内容的提问来源于stack exchange,提问作者Shashikumar N
相关产品推荐
相关产品推荐

