应用情景
经典使用情景:js的一些事件,比如:onresize、scroll、mousemove、mousehover等;
还比如:手抖、手误、服务器没有响应之前的重复点击;
这些都是没有意义的,重复的无效的操作,设置对整个系统的影响还可能是致命的,所以我们要对重复点击的事件进行相应的处理!
节流函数
所谓的节流函数顾名思义,就是某个时刻限制函数的重复调用。
同样节流函数也是为了解决函数重复提交的问题,而防止重复提交的方法,不止节流函数一种实现。
方法汇总
本文整理了我在工作实践当中,觉的防止js重复提交,比较好用的方法,在这里和大家分享一下。
一、setTimeout + clearTimeout(节流函数)
本文提供两种实现方式:普通节流函数和闭包节流函数
二、设定flag/js加锁
三、通过disable
四、添加浮层比如loading图层防止多次点击
具体实现
一、setTimeout + clearTimeout(节流函数)
方式一:闭包节流函数(可传递多个参数)
/** * 闭包节流函数方法(可传参数) * @param Function fn 延时调用函数 * @param Number delay 延迟多长时间 * @return Function 延迟执行的方法 */ var throttle = function (fn, delay) { var timer = null; return function () { var args = arguments; //参数集合 clearTimeout(timer); timer = setTimeout(function () { fn.apply(this, args); }, delay); } } /** * 要执行的方法 * @param String name 传递的参数 */ function postFun(name) { document.writeln("名字:" + name); } //================测试部分 => 【1s重复点击10次】 var t = throttle(postFun, 1000); var ejector = setInterval(() => { t("tiger"); }, 100); setTimeout(() => { clearInterval(ejector); }, 1000);
执行结果:
方式二:普通节流函数方法
/** * 普通节流函数方法 * @param Function fn 延时调用函数 * @param Number delay 延迟多长时间 */ function throttle(fn, delay) { if (fn._id) { clearTimeout(fn._id); } fn._id = window.setTimeout(() => { fn(); fn._id = null; }, delay); } /** * 要执行的方法 */ function postFun() { document.writeln(new Date().getTime()); } //================测试部分 => 【1s重复点击10次】 var interval = setInterval(() => { throttle(postFun, 1000); }, 100); setTimeout(() => { clearInterval(interval); }, 1000);
执行结果:
二、设定flag/js加锁
var lock = false; jQuery("#submit").on('click', function () { if (lock) { return false; } jQuery.post(url, data, function (response) { //TODO:业务代码 lock = false; }); });
总结
前两种方式实现起来比较方便,而后两种实现起来相对比较繁琐,如果是为了防止事件的多次触发,建议使用闭包,如果是表单提交,适度使用后两种比较稳妥。