前端如何防止介面重複提交

喆星高照發表於2024-04-22

什麼是介面重複提交?

介面重複提交指的是在網路通訊中,同一個請求被客戶端多次傳送到伺服器端的情況。這種情況可能由於多種原因導致,例如使用者在等待期間多次點選提交按鈕、網路超時後客戶端重新傳送請求、客戶端傳送的請求在網路傳輸過程中出現重複等。

介面重複提交可能會導致多種問題,當伺服器收到重複請求時,可能會多次處理相同的資料,導致資料重複操作或者產生不一致的結果。重複提交請求會增加伺服器的負載和資源消耗,特別是在高併發情況下,可能會導致伺服器壓力過大,影響系統的效能和穩定性。有些請求是具有副作用的,例如支付、提交訂單等,重複提交可能導致使用者被重複扣款或者重複生成訂單,從而導致業務異常或者使用者不滿。

下面我們就來看看前端有哪些防止介面重複提交的方法。

前端如何防止介面的重複提交?

禁用提交按鈕

在使用者點選提交按鈕後,立即禁用該按鈕,防止使用者多次點選。可以在介面請求結束後重新啟用按鈕。程式碼如下所示。

<form id="myForm">
<!-- 表單內容 -->
<button type="submit" id="submitButton">提交</button>
</form>

<script>
document.getElementById('myForm').addEventListener('submit', function(event) {
event.preventDefault(); // 阻止預設提交行為
document.getElementById('submitButton').disabled = true; // 禁用提交按鈕

// 傳送請求
fetch('/api/submit', {
method: 'POST',
// 請求引數
}).then(function(response) {
// 處理響應
document.getElementById('submitButton').disabled = false; // 啟用提交按鈕
}).catch(function(error) {
console.error('Error:', error);
document.getElementById('submitButton').disabled = false; // 啟用提交按鈕(如果請求失敗)
});
});
</script>

顯示載入狀態

在使用者提交表單後,顯示一個載入狀態的提示,告知使用者正在處理請求,避免使用者重複點選提交按鈕。

<form id="myForm">
<!-- 表單內容 -->
<button type="submit" id="submitButton">提交</button>
<div id="loadingMessage" style="display: none;">正在載入...</div>
</form>

<script>
document.getElementById('myForm').addEventListener('submit', function(event) {
event.preventDefault(); // 阻止預設提交行為
document.getElementById('submitButton').disabled = true; // 禁用提交按鈕
document.getElementById('loadingMessage').style.display = 'block'; // 顯示載入狀態

// 傳送請求
fetch('/api/submit', {
method: 'POST',
// 請求引數
}).then(function(response) {
// 處理響應
document.getElementById('submitButton').disabled = false; // 啟用提交按鈕
document.getElementById('loadingMessage').style.display = 'none'; // 隱藏載入狀態
}).catch(function(error) {
console.error('Error:', error);
document.getElementById('submitButton').disabled = false; // 啟用提交按鈕(如果請求失敗)
document.getElementById('loadingMessage').style.display = 'none'; // 隱藏載入狀態(如果請求失敗)
});
});
</script>

設定防抖或節流

在使用者點選提交按鈕後,使用防抖或節流的技術延遲傳送請求,確保只傳送一次請求。防抖和節流是一種常見的前端效能最佳化技術,可以控制函式的執行頻率。

// 防抖函式
function debounce(func, delay) {
let timer;
return function() {
clearTimeout(timer);
timer = setTimeout(func, delay);
};
}

document.getElementById('submitButton').addEventListener('click', debounce(function() {
// 傳送請求
fetch('/api/submit', {
method: 'POST',
// 請求引數
}).then(function(response) {
// 處理響應
}).catch(function(error) {
console.error('Error:', error);
});
}, 1000)); // 1秒內只允許點選一次

生成請求識別符號

在每次請求前生成一個唯一的請求識別符號(例如 UUID),並將該識別符號作為請求的一部分傳送到後端。後端在接收到請求後,檢查該識別符號是否已經處理過,如果已經處理過則不再處理。前端可以透過記錄請求識別符號的狀態來避免重複提交。

// 生成唯一識別符號
function generateRequestId() {
return Math.random().toString(36).substr(2, 9);
}

let requestId;

document.getElementById('submitButton').addEventListener('click', function() {
requestId = generateRequestId(); // 生成請求識別符號
// 傳送請求
fetch('/api/submit', {
method: 'POST',
headers: {
'X-Request-Id': requestId // 將請求識別符號新增到請求頭中
},
// 請求引數
}).then(function(response) {
// 處理響應
}).catch(function(error) {
console.error('Error:', error);
});
});

使用狀態管理庫

如果前端使用了狀態管理庫(如 Redux、Vuex 等),可以在提交請求前檢查狀態,確保不會重複提交相同的請求。

import store from './store'; // 引入狀態管理庫

document.getElementById('submitButton').addEventListener('click', function() {
if (store.state.isSubmitting) {
return; // 如果正在提交,則不執行後續操作
}
// 設定提交狀態
store.commit('setSubmitting', true);

// 傳送請求
fetch('/api/submit', {
method: 'POST',
// 請求引數
}).then(function(response) {
// 處理響應
store.commit('setSubmitting', false); // 恢復非提交狀態
}).catch(function(error) {
console.error('Error:', error);
store.commit('setSubmitting', false); // 恢復非提交狀態(如果請求失敗)
});
});

介面鎖定

在前端傳送請求前,先檢查是否存在正在處理的相同請求,如果存在則不傳送新的請求。可以使用一個變數來記錄當前正在處理的請求,以防止重複提交。

let isRequesting = false;

document.getElementById('submitButton').addEventListener('click', function() {
if (isRequesting) {
return; // 如果正在請求,則不執行後續操作
}
isRequesting = true; // 鎖定介面

// 傳送請求
fetch('/api/submit', {
method: 'POST',
// 請求引數
}).then(function(response) {
// 處理響應
isRequesting = false; // 解鎖介面
}).catch(function(error) {
console.error('Error:', error);
isRequesting = false; // 解鎖介面(如果請求失敗)
});
});

以上方法可以單獨使用,也可以組合使用,以提高介面請求的可靠性和安全性。

總結

防止介面重複提交是為了確保系統的資料一致性、避免不必要的資源浪費和提升使用者體驗。為了避免介面重複提交帶來的問題,需要在前端和後端都進行相應的處理,例如在前端禁用提交按鈕、顯示載入狀態,在後端實現冪等性檢查等。

相關文章