在前端开发中,页面请求接口大规模并发可能会导致浏览器性能下降、服务器压力过大、接口响应超时等问题。以下是一些常见的解决方法:
1. 限制并发请求数量
通过自定义请求队列,控制同时发起的请求数量,避免过多请求同时发出。
示例代码
javascript
class RequestQueue {
constructor(maxConcurrency) {
this.maxConcurrency = maxConcurrency;
this.currentConcurrency = 0;
this.queue = [];
}
addRequest(request) {
return new Promise((resolve, reject) => {
const task = () => {
this.currentConcurrency++;
request()
.then((result) => {
resolve(result);
})
.catch((error) => {
reject(error);
})
.finally(() => {
this.currentConcurrency--;
if (this.queue.length > 0) {
const nextTask = this.queue.shift();
nextTask();
}
});
};
if (this.currentConcurrency < this.maxConcurrency) {
task();
} else {
this.queue.push(task);
}
});
}
}
// 使用示例
const queue = new RequestQueue(3); // 最大并发数为 3
function fetchData(id) {
return new Promise((resolve) => {
setTimeout(() => {
console.log(`Fetched data for id ${id}`);
resolve(id);
}, 1000);
});
}
const requests = Array.from({ length: 10 }, (_, i) => () => fetchData(i));
requests.forEach((request) => {
queue.addRequest(request).then((result) => {
console.log(`Result: ${result}`);
});
});
2. 合并请求
将多个相关的请求合并为一个请求,减少请求次数。
示例场景
例如,在电商页面中,需要获取多个商品的信息,可以将这些商品的 ID 一次性传递给后端接口,后端返回这些商品的详细信息。
javascript
// 假设我们有多个商品 ID
const productIds = [1, 2, 3, 4, 5];
// 合并请求
fetch(`/api/products?ids=${productIds.join(',')}`)
.then((response) => response.json())
.then((data) => {
console.log(data);
});
3. 节流与防抖
- 节流(Throttle):在一定时间内,只执行一次请求。适用于需要频繁触发的请求,如滚动加载数据。
- 防抖(Debounce):在一定时间内,只有最后一次触发的请求会被执行。适用于搜索框输入提示等场景。
节流示例代码
javascript
function throttle(func, delay) {
let timer = null;
return function() {
if (!timer) {
func.apply(this, arguments);
timer = setTimeout(() => {
timer = null;
}, delay);
}
};
}
// 使用示例
function fetchDataOnScroll() {
console.log('Fetching data on scroll');
// 发起请求
}
window.addEventListener('scroll', throttle(fetchDataOnScroll, 500));
防抖示例代码
javascript
function debounce(func, delay) {
let timer = null;
return function() {
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, arguments);
}, delay);
};
}
// 使用示例
function searchData(query) {
console.log(`Searching for ${query}`);
// 发起搜索请求
}
const input = document.getElementById('search-input');
input.addEventListener('input', debounce((e) => {
searchData(e.target.value);
}, 300));
4. 缓存机制
对于一些不经常变化的数据,可以使用缓存机制,避免重复请求。
示例代码
javascript
const cache = {};
function fetchDataWithCache(url) {
if (cache[url]) {
return Promise.resolve(cache[url]);
}
return fetch(url)
.then((response) => response.json())
.then((data) => {
cache[url] = data;
return data;
});
}
// 使用示例
fetchDataWithCache('/api/data')
.then((data) => {
console.log(data);
});
5. 分批次请求
将大量请求分成多个批次,依次发送请求,避免一次性发送过多请求。
示例代码
javascript
const requests = Array.from({ length: 20 }, (_, i) => () => fetch(`/api/data/${i}`));
const batchSize = 5;
function sendRequestsInBatches() {
const batch = requests.splice(0, batchSize);
if (batch.length === 0) {
return Promise.resolve();
}
const promises = batch.map((request) => request());
return Promise.all(promises).then(() => sendRequestsInBatches());
}
sendRequestsInBatches().then(() => {
console.log('All requests completed');
});