【校招VIP】JavaScript-节流函数的实现

08月23日 收藏 0 评论 0 前端开发

【校招VIP】JavaScript-节流函数的实现

转载声明:文章来源:https://blog.csdn.net/qq_42181069/article/details/121934002

1、对节流函数该怎么理解

日常小案例:

老师在上完课后给大家【五分钟】询问大家有没有什么问题要问

但是在【五分钟】之内,不管有多少同学 来问问题,都只会【解答一个问题】

如果在解答一个问题后,5分钟过后还没有同学问问题,那么就下课

所以用三句话理解就是:

当事件触发时,会触发这个事件的响应函数

当事件密集触发时,节流函数会按照一定的频率来执行函数

不管在这个中间有多少次触发这个事件,执行函数的频率总是固定的

2、拙劣的图解

3、 节流的应用场景

监听页面的滚动事件

鼠标的移动事件

用户频繁点击按钮操作

4、节流的简单实现

//简单实现
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)一定是负数的

//第一次是否立即执行
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、增加功能-最后一次是否执行

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、增加功能-函数返回值

//函数返回值
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、代码测试

<!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>


C 0条回复 评论

帖子还没人回复快来抢沙发