函数的防抖与节流实现
一、什么是节流函数,什么是防抖函数,它们之间的区别是什么?
·节流函数:节流,可以理解为节省流量。当一个请求被用户在短时间内不停点击时(用户频繁发送一个数据请求),为了减轻服务器压力,需要设定一个时间,使得在规定的这个时间内,无论用户请求了多少次,就当一次执行。例子:玩游戏回城按钮按多次等于按一次。
·防抖函数:抖,即抖动。当用户使用搜索框时,输入一个内容就发送一次请求,继续输入则会继续发送(用户一直在发送多个不同的请求),为了防止这种情况发生,应在用户输入结束后延时发请求,而不是同步发送。
·区别:节流函数是将多个重复的请求在规定的时间内执行一次,防抖是将一段时间内不停被执行的不同请求,延迟规定的时间后再执行。
二、节流函数与防抖函数的实现。
1.节流函数
------------------------------------------------------------------------------------------------------------------
//1.基础的节流函数,在规定的时间内执行只一次
function throttle(fn, delay) {
//定义上一次的时间
const lastTime = 0
//真正执行的函数
const doThrottle = function () {
//定义当前调用的时间
const nowTime = new Date().getTime()
//如果当前调用的时间-上一次执行的时间比规定的时间小,即多次触发,则只执行一次
if (delay <= (nowTime - lastTime)) {
//外部传入的函数
fn()
lastTime = nowTime
}
}
return doThrottle
}
------------------------------------------------------------------------------------------------------------------------
// 2.1控制节流第一次是否执行函数--leading
function throttle(fn, delay, options = { leading: true, trailing: false }) {
//定义相关参数
const { leading, trailing } = options
const lastTime = 0
//真正执行函数
const doThrottle = function () {
//定义当前调用时间
const nowTime = new Date().getTime()
//是第一次开始但是不希望执行函数
if (lastTime === 0 && !leading) lastTime = nowTime
//使用当前触发的时间-上一次执行时间与外部传入的时间比较
const remainTime = delay - (nowTime - lastTime)
if (remainTime <= 0) {
//外部传入的函数
fn()
lastTime = nowTime
}
}
return doThrottle
}
---------------------------------------------------------------------------------------------------------------------
// 2.2控制节流最后一次是否执行函数--leading,trailing
function throttle(fn, delay, options = { leading: true, trailing: false }) {
//定义相关参数
const { leading, trailing } = options
const lastTime = 0
const timer = null
//真正执行函数
const doThrottle = function () {
//定义当前调用时间
const nowTime = new Date().getTime()
//是第一次开始但是不希望执行函数
if (lastTime === 0 && !leading) lastTime = nowTime
//使用当前触发的时间-上一次执行时间与外部传入的时间比较
const remainTime = delay - (nowTime - lastTime)
if (remainTime <= 0) {
//防止重复调用
if (timer) {
clearTimeout(timer)
timer = null
}
//外部传入的函数
fn()
//保留上次触发时间
lastTime = nowTime
return
}
//判断是否需要执行最后一次输出
if (trailing && !timer) {
timer = setTimeout(() => {
//执行外部函数
fn()
//防止我们延迟调用函数时,上面时间到了后,又重复调用
lastTime = !leading ? 0 : new Date().getTime()
//清除定时器
timer = null
}, remainTime);
}
}
return doThrottle
}
----------------------------------------------------------------------------------------------------------------------
//3.在上一次优化的前提上使用this
function throttle(fn, delay, options = { leading: true, trailing: false }) {
//定义相关参数
const { leading, trailing } = options
const lastTime = 0
const timer = null
//真正执行函数
const doThrottle = function (...args) {
//定义当前调用时间
const nowTime = new Date().getTime()
//是第一次开始但是不希望执行函数
if (lastTime === 0 && !leading) lastTime = nowTime
//使用当前触发的时间-上一次执行时间与外部传入的时间比较
const remainTime = delay - (nowTime - lastTime)
if (remainTime <= 0) {
//防止重复调用
if (timer) {
clearTimeout(timer)
timer = null
}
//外部传入的函数
fn.apply(this,args)
//保留上次触发时间
lastTime = nowTime
return
}
//判断是否需要执行最后一次输出
if (trailing && !timer) {
timer = setTimeout(() => {
//执行外部函数
fn.apply(this,args)
//防止我们延迟调用函数时,上面时间到了后,又重复调用
lastTime = !leading ? 0 : new Date().getTime()
//清除定时器
timer = null
}, remainTime);
}
}
return doThrottle
}
-----------------------------------------------------------------------------------------------------------------
//4.在上一次优化的前提上添加取消功能
function throttle(fn, delay, options = { leading: true, trailing: false }) {
//定义相关参数
const { leading, trailing } = options
const lastTime = 0
const timer = null
//真正执行函数
const doThrottle = function (...args) {
//定义当前调用时间
const nowTime = new Date().getTime()
//是第一次开始但是不希望执行函数
if (lastTime === 0 && !leading) lastTime = nowTime
//使用当前触发的时间-上一次执行时间与外部传入的时间比较
const remainTime = delay - (nowTime - lastTime)
if (remainTime <= 0) {
//防止重复调用
if (timer) {
clearTimeout(timer)
timer = null
}
//外部传入的函数
fn.apply(this, args)
//保留上次触发时间
lastTime = nowTime
return
}
//判断是否需要执行最后一次输出
if (trailing && !timer) {
timer = setTimeout(() => {
//执行外部函数
fn.apply(this, args)
//防止我们延迟调用函数时,上面时间到了后,又重复调用
lastTime = !leading ? 0 : new Date().getTime()
//清除定时器
timer = null
}, remainTime);
}
}
//取消功能,重置默认值
doThrottle.cancel = function () {
if (timer) clearTimeout(timer)
timer = null
lastTime = 0
}
return doThrottle
}
--------------------------------------------------------------------------------------------------------------------
//5.在上一次优化的前提上添加函数的返回值,使用回调函数callback
function throttle(fn, delay, options = { leading: true, trailing: false }, callback) {
//定义相关参数
const { leading, trailing } = options
const lastTime = 0
const timer = null
//真正执行函数
const doThrottle = function (...args) {
//定义当前调用时间
const nowTime = new Date().getTime()
//是第一次开始但是不希望执行函数
if (lastTime === 0 && !leading) lastTime = nowTime
//使用当前触发的时间-上一次执行时间与外部传入的时间比较
const remainTime = delay - (nowTime - lastTime)
if (remainTime <= 0) {
//防止重复调用
if (timer) {
clearTimeout(timer)
timer = null
}
//返回外部函数调用结果
const result = fn.apply(this, args)
callback(result)
//保留上次触发时间
lastTime = nowTime
return
}
//判断是否需要执行最后一次输出
if (trailing && !timer) {
timer = setTimeout(() => {
//返回外部函数调用结果
const result = fn.apply(this, args)
callback(result)
//防止我们延迟调用函数时,上面时间到了后,又重复调用
lastTime = !leading ? 0 : new Date().getTime()
//清除定时器
timer = null
}, remainTime);
}
}
//取消功能,重置默认值
doThrottle.cancel = function () {
if (timer) clearTimeout(timer)
timer = null
lastTime = 0
}
return doThrottle
}
================================================================
================================================================
2.防抖函数
//1.创建一个基础的防抖函数,延迟执行
function debounce(fn, delay) {
//定义一个定时器,保存上一次的定时器
const timer = null;
//执行函数
const doDebounce = function () {
//取消上一次的定时器
if (timer) {
clearTimeout(timer)
}
//延迟执行
timer = setTimeout(() => {
//外部传入的请求函数
fn()
}, delay)
}
return doDebounce
}
--------------------------------------------------------------------------------------------------------------------------
function debounce(fn, delay,) {
//定义一次定时器,保存上一次的定时器
const timer = null
//真正执行的函数
const doDebounce = function (...args) {
//取消上一次的定时器
if (timer) clearTimeout(timer)
//延迟执行,参数不止一个,采用展开语法
timer = setTimeout(() => {
//外部传入真正要执行的函数
fn.apply(this, args)
}, delay)
}
return doDebounce
}
----------------------------------------------------------------------------------------------------------------
//3.在this的基础上判断是否立即执行
function debounce(fn, delay, immediate = false) {
//定义一个定时器,保存上一次的定时器
const timer = null
const isDone = false
//真正执行的函数
const doDebounce = function (...args) {
//取消上一次的定时器
if (timer) clearTimeout(timer)
//是否立即执行
if (immediate && !isDone) {
//即外部传入的immediate为真,则立即执行
fn.apply(this, args)
isDone = true
}
else {
//延迟执行,参数不止一个,使用展开语法
timer = setTimeout(() => {
//外部传入执行函数
fn.apply(this, args)
isDone = false
}, delay)
}
}
return doDebounce
}
-----------------------------------------------------------------------------------------------------------
//4.在是否立即执行的基础上加入取消功能
function debounce(fn, delay, immediate = false) {
//定义定时器,保存上一个
const timer = null
const isDone = false
//真正执行函数
const doDebounce = function (...args) {
//清除上一个定时器
if (timer) clearTimeout(timer)
//是否立即执行
if (immediate && !isDone) {
fn.apply(this, args)
isDone = true
}
else {
//延迟执行
timer = setTimeout(() => {
fn.apply(this, args)
isDone = false
}, delay)
}
}
//取消,由于函数也可作为对象使用,故添加一个重置函数
doDebounce.cancel = function () {
if (timer) clearTimeout(timer)
timer = null
isDone = false
}
return doDebounce
}
---------------------------------------------------------------------------------------------------------
//5.在加入取消功能上添加返回值,使用Promise返回
function debounce(fn, delay, immediate = false) {
//定义定时器,保存上一个
const timer = null
const isDone = false
//真正执行函数
const doDebounce = function (...args) {
//添加一个Promise对象
return new Promise((resolve, reject) => {
//清除上一个定时器
if (timer) clearTimeout(timer)
//是否立即执行
if (immediate && !isDone) {
//使用Promise的成功回调将其返回
const result = fn.apply(this, args)
if (result) resolve(resolve)
isDone = true
}
else {
//延迟执行
timer = setTimeout(() => {
//调用Promise的失败回调返回结果
const result = fn.apply(this, args)
if (result) reject(result)
}, delay)
}
})
}
//取消,由于函数也可作为对象使用,故添加一个重置函数
doDebounce.cancel = function () {
if (timer) clearTimeout(timer)
timer = null
isDone = false
}
return doDebounce
}

浙公网安备 33010602011771号