仅支持page和size的API下,无限滚动条目增删后的加载方案
解决思路与通用技巧
由于API仅支持page和size参数,且服务器数据可能因删除操作发生变化,本地缓存的分页偏移与服务器实际偏移不再匹配,核心解决思路是基于本地最后一条有效数据的排序标识,反向推导其在服务器当前数据集中的位置,再计算正确的下一页page值。
以下是几种可落地的通用技巧:
1. 利用排序特性模拟游标分页(推荐)
因为返回列表是严格排序的(如字母顺序),可以通过以下步骤定位正确分页:
- 记录本地最后一条数据的标识(比如示例中的
"F")。 - 通过二分查找请求不同
page,找到包含该标识的服务器分页:// 示例:二分查找定位F所在的page let low = 0, high = 10; // high可设为预估最大页码,或动态递增 let targetPage = -1; let targetIndex = -1; while (low <= high) { const mid = Math.floor((low + high) / 2); const pageData = await api.items.get({ page: mid, size: 3 }); const index = pageData.indexOf("F"); if (index !== -1) { targetPage = mid; targetIndex = index; break; } else if (pageData[pageData.length - 1] < "F") { // 当前页最后一条小于目标,目标在更大的page low = mid + 1; } else { // 当前页第一条大于目标,目标在更小的page high = mid - 1; } } - 计算该数据在服务器全量数据中的偏移量:
const offset = targetPage * 3 + targetIndex; - 下一页的page值为
Math.floor((offset + 1) / 3),请求该page后,过滤掉已存在于本地的条目,再补充数据至所需数量(若当前page剩余数据不足,继续请求下一页):const nextPage = Math.floor((offset + 1) / 3); let newItems = await api.items.get({ page: nextPage, size: 3 }); // 过滤本地已有的数据 newItems = newItems.filter(item => !items.includes(item)); // 如果过滤后不足3条,继续请求下一页 while (newItems.length < 3) { const morePage = nextPage + 1; const moreData = await api.items.get({ page: morePage, size: 3 }); const filtered = moreData.filter(item => !items.includes(item)); newItems.push(...filtered); } // 截取前3条加入本地列表 items = [...items, ...newItems.slice(0, 3)];
2. 重置分页锚点(简单但低效)
若数据总量不大,可直接放弃本地累积的page计数,重新从page=0开始加载,直到覆盖本地最后一条数据,再继续加载下一页:
- 从
page=0开始逐页请求,每拿到一页数据就与本地列表对比,找到包含本地最后一条数据的分页。 - 记录该分页的偏移,之后按正常逻辑加载下一页。
- 缺点:数据量大时会产生较多请求,仅适用于小数据集场景。
3. 维护本地校验标记
每次删除本地条目后,标记本地分页偏移已失效,下次加载下一页时,先执行一次“校准”:
- 向API请求当前预估的下一页,对比返回数据的第一条是否符合预期(比如本地最后一条是
F,预期下一页第一条是G)。 - 如果不符合,立即触发上述二分查找或重置锚点的流程,重新定位正确分页。
内容的提问来源于stack exchange,提问作者Michal
相关产品推荐
相关产品推荐

