文章中英模式
布鲁斯前端JS面试题目 - 实现节流函数优化数据请求
学习如何实现节流函数,控制高频事件触发频率,优化滚动加载、频繁API请求等前端性能问题。
文章中英模式
懒得看文章?那就来看视频吧
什么是节流 (Throttle)?
节流是一种优化技术,用于限制函数在一段时间内的执行频率。与防抖(Debounce)仅执行最后一次操作不同,节流确保函数在指定的时间间隔内最多执行一次。
核心原理:固定间隔时间内只执行一次函数,无论事件触发频率多高,效果类似于水龙头的流量控制。
节流应用场景
- 1. 滚动事件处理(如滚动加载、固定导航栏)
- 2. 监听resize事件调整布局
- 3. 拖拽操作更新界面
- 4. 频繁的数据请求或API调用
- 5. 实时游戏中的按键响应
- 6. Canvas 绘图操作
基本实现:节流函数 (Throttle)
以下是两种常见的实现方式:时间戳方法和定时器方法。
方法一:时间戳实现
function throttle(func, delay = 300) {
let lastTime = 0;
return function(...args) {
const now = Date.now();
// 检查距离上次执行是否已经超过延迟时间
if (now - lastTime >= delay) {
func.apply(this, args);
lastTime = now;
}
};
}
方法二:定时器实现
function throttle(func, delay = 300) {
let timer = null;
return function(...args) {
// 如果没有定时器运行中,则设置新的定时器
if (!timer) {
timer = setTimeout(() => {
func.apply(this, args);
timer = null;
}, delay);
}
};
}
方法三:综合方法(首尾调用都不丢失)
function throttle(func, delay = 300) {
let timer = null;
let lastTime = 0;
return function(...args) {
const now = Date.now();
const remaining = delay - (now - lastTime);
// 清除定时器并立即执行
if (remaining <= 0) {
if (timer) {
clearTimeout(timer);
timer = null;
}
func.apply(this, args);
lastTime = now;
} else if (!timer) {
// 设置定时器,确保最后一次操作被执行
timer = setTimeout(() => {
func.apply(this, args);
lastTime = Date.now();
timer = null;
}, remaining);
}
};
}
实际应用:节流优化数据请求
以下是一些节流函数在数据请求中的实际应用:
案例一:滚动加载数据
// 页面滚动时加载更多数据
function loadMoreData() {
console.log('加载更多数据...');
// 计算滚动位置
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
const scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
const clientHeight = document.documentElement.clientHeight || window.innerHeight;
// 滚动到底部附近时,加载更多
if (scrollTop + clientHeight >= scrollHeight - 100) {
fetch('/api/posts?page=' + currentPage)
.then(response => response.json())
.then(data => {
// 处理数据,添加到页面上
displayData(data);
currentPage++;
});
}
}
// 使用节流函数优化滚动事件
const throttledLoadMore = throttle(loadMoreData, 500);
window.addEventListener('scroll', throttledLoadMore);
案例二:即时搜索建议
// 发送搜索请求
function fetchSearchResults(query) {
console.log('搜索:', query);
fetch(`/api/search?q=${encodeURIComponent(query)}`)
.then(response => response.json())
.then(results => {
// 更新搜索结果显示
updateSearchResults(results);
})
.catch(error => {
console.error('搜索错误:', error);
});
}
// 使用节流函数限制请求频率
const throttledSearch = throttle(fetchSearchResults, 300);
// 绑定到输入事件
document.querySelector('#search-input').addEventListener('input', (e) => {
const query = e.target.value.trim();
if (query.length > 2) {
throttledSearch(query);
}
});
节流与防抖比较
节流和防抖都是限制事件处理频率的方法,但适用于不同场景:
特性 | 节流 (Throttle) | 防抖 (Debounce) |
---|---|---|
执行时机 | 固定时间内最多执行一次 | 等待指定时间后执行,期间若再触发则重新计时 |
执行频率 | 稳定固定的频率 | 仅在事件停止后执行一次 |
适用场景 | 滚动加载、拖拽效果、频繁API调用 | 搜索建议、表单验证、窗口调整大小 |
类比 | 水龙头限流 | 电梯等待所有人进入后再启动 |