长列表分页加载时如何避免重复请求和数据错乱?
我在做商品列表的分页加载,每次滚动到底部就调用接口拉下一页数据。但有时候网络慢,用户快速滚动会触发多次请求,导致数据重复或者顺序错乱,咋办?
我试过加个 loading 锁:if (loading) return;,但偶尔还是会出现重复项,特别是用户快速上下滚动的时候。
const loadMore = async () => {
if (loading || !hasMore) return;
loading = true;
const res = await fetch(<code>/api/items?page=${page}</code>);
items.push(...res.data);
page++;
loading = false;
};
第一,前端这边需要双重保险。除了loading状态,还要加个lastRequestId来标记最近一次请求。这样就算用户疯狂滑动,也能保证只处理最后一次请求的结果:
第二,服务端最好也做防重处理。给分页接口加个timestamp参数,超过5秒的旧请求直接拒绝。这样能避免网络延迟导致的乱序问题。
第三,实在不放心的话,可以在合并数据前做去重判断。比如商品列表可以用id检查是否已存在。不过这个算是兜底方案了,前面两个处理好基本够用。
还有个细节,page++最好放在数据合并成功之后,避免请求失败时页码错位。