一. 首先说说为何要防止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的请求,因此更好。