1.概念
节流(throttle)和防抖(debounce)都是优化性能的一种,如当页面resize时候我们要进行一些操作(重新排版或者进行别的操作),当输入框输入数据时我们要进行校验的时候需要使用这些技术。但他们触发函数的方式有些不同:
- 节流是让对应的函数每隔固定的时间执行一次。如页面resize时,我们只需要隔一定时间执行对应的函数就行。
- 防抖是让对应的函数在事件不再触发后执行对应的函数。如对input框中输入的字符串进行校验,等用户不在输入的时候一起发出去校验,而不需要输入一个字符就校验一次。
2.代码
一、节流
- 立即执行版(利用时间戳)(当resize时马上执行一次,但是在不触发resize后不在会执行)
function throttle(fn, wait) {
let cur, pre = 0;
return function (...args) {
cur = +new Date();
if(cur - pre >= wait) {
fn.apply(this, args);
pre = cur;
}
}
}
- 非立即执行版(利用setTimeout)(当resize时不会马上执行一次,但是在不触发resize后还会执行一次)
function throttle(fn, wait) {
let timer = null;
return function (...args) {
if(!timer) {
timer = setTimeout(() => {
timer = null;
fn.apply(this, args)
}, wait);
}
}
}
- 结合版(当resize时会马上执行一次,在不触发resize后还会再执行一次)
function throttle(fn, wait) {
let cur, pre = 0, timer = null;
return function(...args) {
cur = +new Date();
if(cur - pre > wait) {
fn.apply(this, args);
pre = cur;
if(timer) {
clearTimeout(timer);
timer = null;
}
} else if(!timer) {
timer =setTimeout(() => {
fn.apply(this, args);
timer = null;
}, wait);
}
}
}
二、防抖
- 非立即执行版 (触发就清除掉上次的timer,重新绑定)
function debounce(fn, wait) {
let timer = null;
return function (...args) {
if(timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(this, args)
}, wait);
}
}
- 立即执行版
function debounce(fn, wait) {
let timer = null;
return function (...args) {
if(!timer) fn.apply(this, args);
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, wait);
}
}
- 可配置版(默认非立即执行版)
function debounce(fn, wait, immediate = false) {
let timer = null;
return function (...args) {
clearTimeout(timer);
if(immediate) {
if(!timer) fn.apply(this, args);
}
timer = setTimeout(() => {
fn.apply(this, args);
}, wait);
}
}