REST API load more请求新增数据干扰offset导致重复的应对策略
最优解决方案:改用基于游标的分页(Keyset Pagination)
你遇到的是offset分页的天生缺陷:offset的本质是跳过指定数量的返回结果,当有新数据插入列表头部时,原有数据的位置会整体后移,偏移量对应的内容自然就会和之前加载的内容重复。这种问题靠调整offset数值根本解决不了,直接换掉分页方式就行。
具体实现逻辑
你现在的排序规则默认是新数据在前(不然不会出现插入打乱offset的问题),直接用排序字段+主键作为游标即可:
- 接口新增两个查询参数
last_created_at(对应你排序用的时间字段)、last_id(对应数据的唯一主键),废弃offset参数 - 首次加载直接发请求
GET /v1/endpoint?limit=6,拿到返回的6条数据后,记录最后一条数据的created_at和id作为游标 - 后续点击加载更多时,携带上次记录的游标发请求:
GET /v1/endpoint?limit=6&last_created_at=xxx&last_id=xxx - 服务端查询时直接做条件过滤,示例SQL逻辑:
SELECT * FROM 你的表 WHERE (created_at < '上次返回的最后一条的created_at') OR (created_at = '上次返回的最后一条的created_at' AND id < '上次返回的最后一条的id') ORDER BY created_at DESC, id DESC LIMIT 6 - 前端每次拿到返回结果后,只要返回的条数小于
limit,就说明已经加载完全部数据,直接隐藏加载更多按钮即可。
方案优势
- 完全不受新增数据影响:游标是基于你已经加载的最后一条数据的实际字段值,不管头部插入多少新数据,每次请求都是从你上次加载的结束位置往后取,不会出现重复也不会漏数据
- 性能远优于offset分页:数据量越大优势越明显,
offset 10000 limit 6需要扫描10006条数据,用游标过滤只需要扫描符合条件的6条,查询速度快很多 - 前端改造成本极低:不需要再维护offset计数,只需要每次请求后更新游标值就行
后端暂时无法改接口的临时兼容方案
如果后端短时间内没法调整分页逻辑,可以先在前端做去重兼容:
- 前端维护一个已加载数据ID的
Set结构,每次拿到新返回的列表后,先过滤掉ID已经存在于Set中的条目,再追加到展示列表中 - 这个方案只是临时补丁,会浪费请求流量,数据量大了也会有性能问题,优先建议改用游标分页。
内容的提问来源于stack exchange,提问作者Toby Scott
相关产品推荐
相关产品推荐

