转载声明:文章来源:https://blog.csdn.net/qq_42181069/article/details/121934002
1、对节流函数该怎么理解
日常小案例:
老师在上完课后给大家【五分钟】询问大家有没有什么问题要问
但是在【五分钟】之内,不管有多少同学 来问问题,都只会【解答一个问题】
如果在解答一个问题后,5分钟过后还没有同学问问题,那么就下课
所以用三句话理解就是:
当事件触发时,会触发这个事件的响应函数
当事件密集触发时,节流函数会按照一定的频率来执行函数
不管在这个中间有多少次触发这个事件,执行函数的频率总是固定的
2、拙劣的图解
3、 节流的应用场景
监听页面的滚动事件
鼠标的移动事件
用户频繁点击按钮操作
4、节流的简单实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | //简单实现 function throttle(fn, interval) { //1.记录上一次的开始时间 let lastTime = 0 //2.事件触发时,真正的执行函数 const _throttle = function (...args) { //2.1 获取当前事件触发时的时间 const nowTime = new Date().getTime() //2.2 使用当前触发的时间和之前的时间间隔以及上一次开始的时间, 计算出还剩余多长事件需要去触发函数 const remainTime = interval - (nowTime - lastTime) if (remainTime <= 0) { //2.3 真正触发函数 fn.apply( this , args) //2.4 保留上次触发的时间 lastTime = nowTime } } return _throttle } |
5、增加功能-第一次是否立即执行
注意:第一次是会立即执行的,lastTime为0,nowTime是个很大的值,interval - (nowTime - lastTime)一定是负数的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | //第一次是否立即执行 function throttle(fn, interval, options = {leading: true }) { //1.记录上一次的开始时间 let lastTime = 0 const { leading } = options //2.事件触发时,真正的执行函数 const _throttle = function (...args) { //2.1 获取当前事件触发时的时间 const nowTime = new Date().getTime() if (!lastTime && !leading) lastTime = nowTime //2.2 使用当前触发的时间和之前的时间间隔以及上一次开始的时间, 计算出还剩余多长事件需要去触发函数 const remainTime = interval - (nowTime - lastTime) if (remainTime <= 0) { //2.3 真正触发函数 fn.apply( this , args) //2.4 保留上次触发的时间 lastTime = nowTime } } return _throttle } |
6、增加功能-最后一次是否执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | function throttle(fn, interval, options = {leading: true ,trailing: false }) { //1.记录上一次的开始时间 let lastTime = 0 let timer = null const { leading, trailing } = options //2.事件触发时,真正的执行函数 const _throttle = function (...args) { //2.1 获取当前事件触发时的时间 const nowTime = new Date().getTime() if (!lastTime && !leading) lastTime = nowTime //2.2 使用当前触发的时间和之前的时间间隔以及上一次开始的时间, 计算出还剩余多长事件需要去触发函数 const remainTime = interval - (nowTime - lastTime) if (remainTime <= 0) { if (timer) { clearTimeout(timer) timer = null } //2.3 真正触发函数 fn.apply( this , args) //2.4 保留上次触发的时间 lastTime = nowTime return } //2.3 最后一次是否执行 if (trailing && !timer) { timer = setTimeout(() => { timer = null lastTime = !leading ? 0 : new Date().getTime() fn.apply( this , args) }, remainTime) } } return _throttle } |
7、增加功能-函数返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | //函数返回值 function throttle(fn, interval, options = {leading: true ,trailing: false }) { //1.记录上一次的开始时间 let lastTime = 0 let timer = null const { leading, trailing, resultCallback } = options //2.事件触发时,真正的执行函数 const _throttle = function (...args) { return new Promise((resolve, reject) => { //2.1 获取当前事件触发时的时间 const nowTime = new Date().getTime() if (!lastTime && !leading) lastTime = nowTime //2.2 使用当前触发的时间和之前的时间间隔以及上一次开始的时间, 计算出还剩余多长事件需要去触发函数 const remainTime = interval - (nowTime - lastTime) if (remainTime <= 0) { if (timer) { clearTimeout(timer) timer = null } //2.3 真正触发函数 const result = fn.apply( this , args) if (resultCallback) resultCallback(result) resolve(result) //2.4 保留上次触发的时间 lastTime = nowTime return } //2.3 最后一次是否执行 if (trailing && !timer) { timer = setTimeout(() => { timer = null lastTime = !leading ? 0 : new Date().getTime() const result = fn.apply( this , args) if (resultCallback) resultCallback(result) resolve(result) }, remainTime) } }) } _throttle.cancel = function () { if (timer) clearTimeout(timer) timer = null lastTime = 0 } return _throttle } |
8、代码测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | <!DOCTYPE html> <html lang= "en" > <head> <meta charset= "UTF-8" > <meta http-equiv= "X-UA-Compatible" content= "IE=edge" > <meta name= "viewport" content= "width=device-width, initial-scale=1.0" > <title>Document</title> </head> <body> <input type= "text" > <button id= "cancel" >取消</button> <script src= "./throttle.js" ></script> <script> const inputEl = document.querySelector( "input" ) let counter = 0 const inputChange = function (event) { console.log(`发送了第${++counter}次网络请求`, this , event) // 返回值 return "当地小有名气的可爱鬼" } //简单版本 inputEl.oninput = throttle(inputChange, 2000) // 1、测试是否立即执行 inputEl.oninput = throttle(inputChange, 2000, { leading: false }) inputEl.oninput = throttle(inputChange, 2000, { leading: true }) //1.1 测试最后一次是否执行 inputEl.oninput = throttle(inputChange, 2000, { leading: true , trailing : true }) inputEl.oninput = throttle(inputChange, 2000, { leading: true , trailing: false }) //2、测试取消功能 const throttleChange = throttle(inputChange, 2000, { leading: true , trailing: false }) const cancelBtn = document.querySelector( '#cancel' ) cancelBtn.onclick = function () { throttleChange.cancel() } // // 3、测试函数带返回值 const _throttle = throttle(inputChange, 1000, { leading: false , trailing: true , resultCallback: function (res) { console.log( "resultCallback:" , res) } }) inputEl.oninput = _throttle const tempCallback = (...args) => { _throttle.apply(inputEl, args).then(res => { console.log( "Promise:" , res) }) } inputEl.oninput = tempCallback </script> </body> </html> |
帖子还没人回复快来抢沙发