节流
事件触发后,规定时间内,事件处理函数不能再次被调用。
也就是说在规定的时间内,函数只能被调用一次,且是最先被触发调用的那次。
举例
:英雄联盟中的技能冷却时间,也就是技能CD,用一次后,过若干秒才能用下一次
使用场景
: 滚动加载更多、搜索框搜的索联想功能、高频点击、表单重复提交……
const throttle = (fn, delay) => { let timer = null return (...args) => { if(timer) {return} // 如果还在cd,就return fn.call(undefined, ...args) //放技能 timer = setTimeout(()=>{ timer = null // cd已过 }, delay) } } const fn = throttle( () => {console.log("我是个放技能函数")}, 3000)
防抖
多次触发事件,事件处理函数只能执行一次,并且是在触发操作结束时执行。
也就是说,当一个事件被触发,准备执行事件函数前,会等待一定的时间(这时间是码农自己去定义的,比如 1 秒),如果没有再次被触发,那么就执行,如果被触发了,那就本次作废,重新从新触发的时间开始计算,并再次等待 1 秒,直到能最终执行!
举例
:我们在玩英雄联盟时,回城需要8秒。如果你因为某种原因(被小兵打,自身移动了)脱离了回城状态,那么需要重新回城,重新计算这8秒。这个过程,我们便可以理解为是防抖。
应用场景
:搜索框搜索输入,并在输入完以后自动搜索、手机号,邮箱验证输入检测、窗口大小 resize 变化后,再重新渲染。
const debounce = (handleTP, delay) => { let timer = null return (...args)=>{ if(timer !== null) { // 第一次进入,timer没有被赋值,不会进入此判断。 clearTimeout(timer) // 清空计时器,相当于打断回城 } timer = setTimeout(()=>{ // 开始计时,相当于按下了回城键 handleTP.call(undefined, ...args) // 调用回城方法 timer = null }, delay) } } const fn = debounce( () => {console.log("我是个回城函数")}, 3000)
关于setTimeout与clearTimeout的小补充
setTimeout() 方法的返回值不是空,而是一个唯一的数值,这个数值有什么用呢?
如果你想要终止 setTimeout() 方法的执行,那就必须使用 clearTimeout() 方法来终止
而使用这个方法的时候,因为你可能同时调用了好几个 setTimeout() 方法,所以系统必须知道你到底要终止的是哪一个 setTimeout() 方法
这样 clearTimeout() 方法就需要一个参数,这个参数就是 setTimeout() 方法的返回值 (数值),用这个数值来唯一确定结束哪一个 setTimeout() 方法。