二、如何避免请求乱序?
1. 前端场景解决方案
方法 1:队列化请求(Sequential Requests)
let requestQueue = Promise.resolve(); // 初始化队列
function sendSequentialRequest(url, data) {
requestQueue = requestQueue.then(async () => {
const response = await fetch(url, { method: 'POST', body: data });
return response.json();
});
return requestQueue;
}
// 使用示例
sendSequentialRequest('/api/page1', { page: 1 });
sendSequentialRequest('/api/page2', { page: 2 }); // 确保在 page1 之后执行
方法 2:取消过期请求(Abort Previous Requests)
原理:当新请求发起时,取消未完成的旧请求。
实现(使用 AbortController):
let abortController = null;
async function fetchData(url) {
if (abortController) {
abortController.abort(); // 取消之前的请求
}
abortController = new AbortController();
try {
const response = await fetch(url, {
signal: abortController.signal
});
const data = await response.json();
// 处理数据
} catch (err) {
if (err.name !== 'AbortError') {
console.error('请求失败:', err);
}
}
}
方法 3:标记请求(Request Tagging)
let latestRequestId = 0;
async function fetchData(url) {
const requestId = ++latestRequestId;
const response = await fetch(url);
const data = await response.json();
// 仅处理最新的请求
if (requestId === latestRequestId) {
updateUI(data);
}
}
2. 后端/分布式场景解决方案
方法 1:顺序锁(Sequential Lock)
from threading import Lock
resource_lock = Lock()
def handle_request(data):
with resource_lock: # 获取锁
process_data(data) # 顺序处理
方法 2:版本号控制(Versioning)
UPDATE table SET value = new_value, version = version + 1
WHERE id = 123 AND version = current_version;