Angular单端点重复分页请求从Promise转为RxJS Observable实现
Angular Promise分页拉取全量数据转Observable实现方案
需求背景
Angular开发中需要将当前可运行的、基于Promise(async/await)实现的单接口分页拉取全量数据逻辑,改用Observables方案实现。
接口支持传入pageSize、page等分页和排序参数,不传参时返回接口最大允许条数(当前为1000条),数据总条数最高可达数万级,也可能仅存在少量数据。
API固定返回格式
{ items: [...], // 对象数组 totalNumberOfItems: 123 // 数据库中符合条件的总条目数 }
现有Promise实现(已省略try-catch和非必要逻辑)
async getAllItems(): Promise<any[]> { let page: number = 1; let pageSize: number; let items: any[] = []; let totalNumberOfItems: number; // 初始httpClient调用默认返回Observable let initialResponse = await this.someService.getItems().toPromise(); items = [...items, ...initialResponse.items]; pageSize = initialResponse.items.length; totalNumberOfItems = initialResponse.totalNumberOfItems; // 循环拉取直到拿完全量数据 while (initialResponse.items.length < initialResponse.totalNumberOfItems) { page++; let nextResponse = await this.someService.getItems({ page, pageSize }).toPromise(); items = [...items, ...nextResponse.items]; } return items; }
初始Observable实现思路框架
interface IResponse { items: any[]; totalNumberOfItems: number; } getAllItems(): Observable<IResponse> { let page: number = 1; let pageSize: number; let totalNumberOfItems: number; return this.someService.getItems().pipe( tap(res => { pageSize = res.items.length; totalNumberOfItems = res.totalNumberOfItems; }), // 待实现:基于初始请求返回的参数迭代调用getItems,拼接所有返回结果 ); }
已验证的可行实现方案(仍有优化空间)
getAllItems(): Observable<ItemsResponse> { let page: number = 1; let pageSize: number; let totalNumberOfItems: number; return this.service.getItems().pipe( tap(response => { pageSize = response.items.length; totalNumberOfItems = response.totalNumberOfItems; }), expand(response => { if (response.items.length < totalNumberOfItems) { const numRepeats = Math.ceil(totalNumberOfItems / pageSize); return (page < numRepeats) ? this.service.getItems({ page++, pageSize }) : EMPTY; } else { return EMPTY; } }), reduce((acc, response) => { acc.Items = [...acc.Items, ...response.Items]; return acc; }) ); }
内容的提问来源于stack exchange,提问作者ShockKhay
相关产品推荐
相关产品推荐

