为了实现全局请求的截流(throttling),我们可以通过一个中间件或者拦截器来处理所有的 HTTP 请求,确保在一定时间间隔内只发送一次请求。对于 Vue 项目来说,通常会使用 axios 或者类似的 HTTP 客户端库来进行网络请求。我们将基于 axios 来创建一个简单的全局请求截流实例。
实现思路
- 定义一个 Map:用来存储每个请求 URL 和最后一次成功发起的时间戳。
- 设置一个时间窗口:在这个时间段内不允许重复发起相同的请求。
- 创建一个 Axios 拦截器:在请求发送之前检查是否满足时间窗口的要求。
- 处理异常情况:比如如果请求被取消或失败了,应该允许重新尝试。
全局请求截流实例代码
import axios from 'axios';
import { throttle } from 'lodash'; // 如果你想用 lodash 的 throttle 函数也可以
// 创建一个新的 axios 实例
const http = axios.create({
baseURL: 'https://api.example.com', // 你的 API 基础地址
timeout: 5000, // 请求超时时间
});
// 存储最近一次请求的时间戳
const requestTimestamps = new Map();
// 时间窗口 (毫秒)
const THROTTLE_WINDOW = 1000; // 例如设置为 1 秒
// 截流函数
function throttleRequest(url) {
const now = Date.now();
if (requestTimestamps.has(url)) {
const lastTime = requestTimestamps.get(url);
if (now - lastTime < THROTTLE_WINDOW) {
console.log(`Throttling request to ${url}`);
return false;
}
}
requestTimestamps.set(url, now);
return true;
}
// 添加请求拦截器
http.interceptors.request.use(
config => {
// 检查是否需要截流
if (!throttleRequest(config.url)) {
return Promise.reject(new Error('Request throttled'));
}
// 如果通过了截流检查,则继续执行请求
return config;
},
error => {
// 请求错误处理
return Promise.reject(error);
}
);
// 添加响应拦截器
http.interceptors.response.use(
response => {
// 成功响应后更新时间戳
if (response.config.url) {
requestTimestamps.set(response.config.url, Date.now());
}
return response;
},
error => {
// 处理响应错误
if (error.response && error.response.config.url) {
// 如果请求失败了,允许立即重试
requestTimestamps.delete(error.response.config.url);
}
return Promise.reject(error);
}
);
export default http;
使用 Lodash 的 throttle 方法
如果你更倾向于使用像 Lodash 这样的库提供的 throttle 函数,可以这样改写:
import axios from 'axios';
import { throttle } from 'lodash';
const http = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000,
});
// 使用 lodash 的 throttle 函数包装 axios 请求方法
http.request = throttle(http.request, THROTTLE_WINDOW, { trailing: false });
export default http;
这种方法更加简洁,但需要注意的是,Lodash 的 throttle 是针对函数调用的节流,它并不直接适用于我们的场景,因为我们需要根据不同的 URL 来做节流控制。因此,第一种方法是更适合这个需求的解决方案。
注意事项
- 在实际应用中,你可能还需要考虑更多的细节,比如如何处理 POST 请求中的不同参数组合,因为它们可能会被视为不同的请求。
- 如果你需要支持更复杂的逻辑,比如根据不同的 HTTP 方法、查询参数等进行更细粒度的截流控制,那么你可能需要对上面的代码进一步扩展。
- 确保你不会意外地阻止了必要的请求,尤其是在用户交互频繁的情况下,如搜索框输入时触发的自动补全请求。