一. 首先說說爲何要防止ajax重複提交,有時候咱們會遇到一下幾種狀況:ajax
狀況1:點擊一次按鈕就會發送一次ajax請求,用戶瘋狂的快速點擊該按鈕,密且快的ajax請求會讓咱們的服務器壓力山大。咱們必須採起必定的機制防止。服務器
狀況2:用戶點擊不那麼頻繁,可是第一請求的數據量較多,花費的時間較長,第二次請求的數據較少,比第一次請求的數據早回來,先顯示在界面上,等到第一次的數據回來以後,再把數據顯示,就會覆蓋掉第二次的顯示的數據,這樣讓用戶體驗很很差。網絡
如今根據我的水平總結了一下幾種辦法。異步
二. 解決ajax重複提交請求的辦法函數
1. 讓其點擊的按鈕disable,讓其不能點擊post
這兒以登陸按鈕爲例this
(function ($) { $('.J-login').click(function () { var loginBtn = this; //1.先進行表單驗證 //...... //2.讓提交按鈕失效,以實現防止按鈕重複點擊 $(loginBtn).attr('disabled', 'disabled'); //3.給用戶提供友好狀態提示 $(loginBtn).text('登陸中...'); //4.異步提交 $.ajax({ url: 'login.do', data: $(this).closest('form[name="loginForm"]').serialize(), type: 'post', success: function(msg){ if (msg === 'ok') { alert('登陸成功!'); //TODO 其餘操做... } else { alert('登陸失敗,請從新登陸!'); //5.讓登錄按鈕從新有效 $(loginBtn).removeAttr('disabled'); } } }); }); })(jQuery);
能夠發現,當登陸失敗後,須要從新讓登陸按鈕具備登陸事件。url
固然,咱們能夠用一個更加優雅的方式來代替之。spa
(function ($) { $('.J-login').click(function () { var loginBtn = this; //1.先進行表單驗證 //...... //2.異步提交 $.ajax({ url: 'login.do', data: $(this).closest('form[name="loginForm"]').serialize(), type: 'post', beforeSend: function () { //3.讓提交按鈕失效,以實現防止按鈕重複點擊 $(loginBtn).attr('disabled', 'disabled'); //4.給用戶提供友好狀態提示 $(loginBtn).text('登陸中...'); }, complete: function () { //5.讓登錄按鈕從新有效 $(loginBtn).removeAttr('disabled'); }, success: function(msg){ if (msg === 'ok') { alert('登陸成功!'); //TODO 其餘操做... } else { alert('登陸失敗,請從新登陸!'); } } }); }); })(jQuery);
2 用setTimeout+clearTimeout方法,防止大量重複點擊code
相信你們碰到過這樣的業務,咱們容許它重複點擊(或者其餘用戶事件),可是不容許在必定的時間內超過次數XX次。這從用戶友好體驗及服務器承受壓力選取了一個折中方案。
var timer = null; $(input).keyup(function(){ var value = $(this).val(); clearTimeout(timer); //若是鍵盤敲擊速度太快,小於100毫秒的話就不會向後臺發請求,可是最後總會進行一次請求的。 timer = setTimeout(function() { //觸發請求 $.ajax({ url: 'typeahead.do', type: 'get', data: value, success: function () { //顯示匹配結果 //...... } }); },100); });
這種辦法的方法就是當用戶瘋狂的快速點擊的時候,只要時間沒有查過100毫秒,就會被取消,只有最後一次會被髮送出去。
3 每次發送ajax前,取消以前沒有返回的一樣的ajax請求,就是abort掉
其實Ajax請求的XMLHttpRequest對象有abort方法,在發送以前把以前沒有返回的ajax請求取消。
取消當前響應,關閉鏈接而且結束任何未決的網絡活動。
這個方法把 XMLHttpRequest 對象重置爲 readyState 爲 0 的狀態,而且取消全部未決的網絡活動。例如,若是請求用了太長時間,並且響應再也不必要的時候,能夠調用這個方法。
僞代碼以下:
if(xmlhttp&&xmlhttp.readyState<4) { xmlhttp.abort(); }
三 .總結
第1種方法通常用於表單提交數據,防止重複提交,像登錄按鈕之類的東西。但不適合與請求資源,用戶體驗很差
第2種方法是作防止用戶瘋狂快速點擊時產生的大量ajax請求,適合用於請求資源之類的地方使用,可是解決不了狀況2的這種狀況。
第3中方法適合於也是請求資源,且能夠解決就是點擊不頻繁,且第二個請求比第一個早回來的狀況。那爲何請求資源的時候不都用這種辦法呢?
緣由是因爲這種辦法雖然均可以解決,可是仍是會消耗服務器的資源,而第二種方法在源頭就撲滅了發送ajax的請求,因此更好。