JS无限滚动问题:需每次加载10条API数据而非批量加载
解决无限滚动时重复加载大量数据的问题
问题原因
当前代码的scroll事件在滚动过程中会被高频触发,当滚动到接近底部时,scrollTop + clientHeight >= scrollHeight -5的条件会多次满足,导致page被连续递增,同时多次调用loadQuotes发起多个API请求,最终加载大量额外数据。
解决方案
添加加载状态锁,避免在请求未完成时触发新的加载操作:
- 新增
isLoading变量标记当前是否正在加载数据 - 在滚动触发逻辑中先检查加载状态,仅当未加载时执行请求
- 确保请求完成(无论成功或失败)后重置加载状态
修改后的完整JavaScript代码
const quotes = document.getElementById("quotes"); const loader = document.getElementById("loader"); let page = 1; let isLoading = false; // 新增加载状态锁 const hideLoader = () => { loader.classList.remove("show"); }; const showLoader = () => { loader.classList.add("show"); }; const getQuotes = async(page) => { isLoading = true; // 标记为加载中 const quotesUrl = `https://api.javascripttutorial.net/v1/quotes/?page=${page}&limit=10`; showLoader(); try { const response = await fetch(quotesUrl); if (!response.ok) { throw new Error(`An error has occured: ${response.status}`); } const json = await response.json(); showQuotes(json.data); } catch (error) { console.error(error); // 可在此添加错误提示逻辑 } finally { hideLoader(); isLoading = false; // 请求完成后重置状态 } }; const showQuotes = (array) => { array.forEach((quote) => { // 用forEach替代map,语义更贴合(无需返回数组) const quoteElement = document.createElement("blockquote"); quoteElement.classList.add("quote"); quoteElement.innerHTML = `<span>${quote.id})</span> ${quote.quote} <footer>${quote.author}</footer>`; quotes.appendChild(quoteElement); }); }; const loadQuotes = (page) => { showLoader(); setTimeout(() => { getQuotes(page); }, 500); }; document.addEventListener("scroll", () => { const { scrollTop, clientHeight, scrollHeight } = document.documentElement; console.log( `scrollTop - ${scrollTop} clientHeight - ${clientHeight} scrollHeight - ${scrollHeight}` ); // 增加加载状态判断,避免重复触发请求 if (scrollTop + clientHeight >= scrollHeight - 5 && !isLoading) { page++; console.log(page); loadQuotes(page); } }); getQuotes(page);
额外优化说明
- 使用
forEach替代map:因为此处仅需遍历数组创建DOM元素,不需要利用map返回的新数组,语义更清晰 - 新增
try/catch/finally:确保API请求无论成功或失败,都会重置isLoading状态,避免后续无法触发新的加载
内容的提问来源于stack exchange,提问作者Mandy23
相关产品推荐
相关产品推荐

