防抖和节流
解释
- 防抖(Debounce):确保在指定时间内函数只执行一次,常用于输入框的搜素建议
- 节流(Throttle):确保在指定时间间隔内函数执行一次,常用于窗口的resize/scroll事件
防抖
function debounce(func, wait) {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => {
fun.apply(this, args);
}, wait)
}
}
//使用防抖函数
const debouncedFetchData = debounce((query)=> {
fetchData(`/api/search?q=${query}`).then(data => {
console.log(data)
})
}, 300);
//输入框事件监听
document.getElementById('search-input').addEventListener('input', (event) => {
debouncedFetchData(event.target.value);
})
节流
function throttle(func, limit) {
let inThrottle;
return function(...args) {
if(!inThrottle) {
func.apply(this, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
}
}
//使用节流函数
const throttleFetchData = throttle(() => {
fetchData('/api/updates').then(data => {
console.log(data);
})
},1000)
//窗口滚动事件监听
window.addEventListener('scroll', throttledFetchData);
如何解决页面请求接口大规模并发问题
1.大数据请求场景下,我们选用了请求队列,封装请求队列
2.防抖节流,用户交互层面上去解决减少请求的处理
3.分页、滚动加载,可视区绘制
大文件上传
背景
涉及到用户自定模型(1G以上)
经常遇到一些问题
- 网络断开之后,之前传的没了
- 传着传着,网络波动了,结果啥都没了
- 关机了,想接着传,做不到
专业术语
- 断电续传
- 断开重连重传
- 切片上传
方案
- 前端切片 chunk 1024M(1048576K),500K,const size = 1048576/500
- 将切片传递给后端,切的片要取名:hash,index
- 后端组合切片
给面试官加料
- 前端切片:主进程做卡顿,web-worker 多线程切片,处理完后交给主进程发送
- 切完后,将blob,存错到IndexedDB,下次用户进来之后,嗅探一下是否存在未完成上传的切片,有就继续上传
- websocket,实时通知,和请求序列的控制wss
- 整体说一说主导这个大文件上传器整体设计
- 组件设计
- props、事件、状态
- 拖拽上传、多文件选择
- 通用化不同文件的上传,上传统一协议
落地
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chunk File Upload</title>
</head>
<body>
<input type="file" id="fileInput">
<button onclick="uploadFile()">Upload</button>
</body>
<script>
const CHUNK_SIZE = 5 * 1024 * 1024; //每块大小为5MB
function uploadFile() {
const file = document.getElementById('fileInput').files[0];
if(!file) {
alert('Please select a files');
return;
}
const totalChunks = Math.ceil(file.size / CHUNK_SIZE);
let currentChunk = 0;
function uploadChunk() {
if(currentChunk >= totalChunks) {
console.log('Upload complete');
return;
}
const start = currentChunk * CHUNK_SIZE;
const end = Math.min(start + CHUNK_SIZE, file.size);
const chunk = file.slice(start, end);
const formData = new FormData();
formData.append('file', chunk);
formData.append('chunkNumber', currentChunk + 1);
formData.append('totalChunks', totalChunks);
fetch('/upload', {
method: 'POST',
body: formData
}).then(response => {
if(response.ok) {
currentChunk ++;
uploadChunk(); //递归调用上传下一块
} else {
console.error('Chunk upload failed');
}
}).catch(error => {
console.error('Upload error', error)
})
}
uploadChunk();
}
</script>
</html>