性能优化篇 防抖和节流
防抖(debounce)
what
事件触发的规定时间内只运行最后一次
when
- 搜索框实时搜索
- 获取鼠标最后移动位置
- 窗口尺寸变换
how
定时器思路:用户触发后,判断是否含有旧定时器,含有则清空, 定义一个新的定时器,时间自定,内部是应用代码。
/**
* 声明 定时器
* @type {number | undefined}
*/
let Timer;
/**
* 防抖函数
* @param {function} fun 要执行的回调函数
* @param {number} t 时间差
*/
function Debounce(fun, t = 500) {
// 含有旧定时器?清空
Timer && clearTimeout(Timer);
// 定义定时器,执行应用代码
Timer = setTimeout(() => {
fun();
}, t);
}
封装
全局变量模式
/** * 声明 定时器 * @type {number | undefined} */ let Timer; /** * 防抖函数 * @param {function} fun 要执行的回调函数 * @param {number} t 时间差 */ function Debounce(fun, t = 500, ...rest) { // 含有旧定时器?清空 Timer && clearTimeout(Timer); // 定义定时器,执行应用代码 Timer = setTimeout(() => { fun.apply(this, rest); }, t); }
example
Debounce((a, b)=>{console.log(a, b);}, 3000, 'hello', 'world')
闭包模式
/** * 防抖函数 * @param {function} fun 要执行的回调函数 * @param {number} t 时间差 * @returns {function} */ function Debounce(fun, t = 500) { let Timer; return function (...rest) { // 含有旧定时器?清空 Timer && clearTimeout(Timer); // 定义定时器,执行应用代码 Timer = setTimeout(() => { fun.apply(this, rest); }, t); } }
example
function fun(a, b) { console.log(a + b); } const newPrint = Debounce(fun, 3000); newPrint('hello', 'world');
带返回值的封装封装
全局变量模式
/** * 声明 定时器 * @type {number | undefined} */ let Timer; /** * 防抖函数 * @param {function} fun 要执行的回调函数 * @param {number} t 时间差 */ function Debounce(fun, t = 500, ...rest) { // 含有旧定时器?清空 Timer && clearTimeout(Timer); return new Promise(resolve => { // 定义定时器,执行应用代码 Timer = setTimeout(() => { resolve(fun.apply(this, rest)); }, t); }) }Example
function add(a, b) { return a + b; } Debounce(add, 3000)('1', '2').then(res => { console.log('res:', res); })
闭包模式
/** * 防抖函数 * @param {function} fun 要执行的回调函数 * @param {number} t 时间差 * @returns {function} 抛出函数 */ function Debounce(fun, t = 500) { let Timer; return function (...rest) { return new Promise((resolve) => { // 含有旧定时器?清空 Timer && clearTimeout(Timer); // 定义定时器,执行应用代码 Timer = setTimeout(() => { resolve(fun.apply(this, rest)); }, t); }); } }
Example
function fun(a, b) { return a + b; } const print = Debounce(fun, 3000); // promise then回调函数 print('1', '2').then(res => { console.log('res:', res); }) // await let res = await print('1', '2'); console.log(res);
节流(Throttle)
what
规定时间内,只触发一次应用程序
when
- 点击按钮
- 页面滚动
- 动画场景
how
如果在时间范围外,运行应用程序,设置一个时间范围
/**
* 声明 运行变量
* @type {boolean}
*/
let active;
/**
* 节流函数
* @param {function} fun 要执行的回调函数
* @param {number} t 时间差
*/
function Throttle(fun, t = 500) {
// 没有运行
if (!active) {
// 运行应用程序
fun();
// 设置时间范围
active = true;
setTimeout(()=> {
active = false;
}, t);
}
}
封装
全局变量模式
/** * 声明 运行变量 * @type {boolean} */ let active; /** * 节流函数 * @param {function} fun 要执行的回调函数 * @param {number} t 时间差 * @param {...any} rest 回调函数所需参数 */ function Throttle(fun, t = 500, ...rest) { // 在时间范围外 if (!active) { // 运行应用程序 fun.apply(this, rest); // 设置时间范围 active = true; setTimeout(()=> { active = false; }, t); } }
example
Throttle((a, b)=>{console.log(a, b);}, 3000, 'hello', 'world');
闭包模式
/** * 节流函数 * @param {function} fun 要执行的回调函数 * @param {number} t 时间差 * @returns {function} 返回函数 */ function Throttle(fun, t = 500) { let active; return function(...rest) { // 在时间范围外 if (!active) { // 运行应用程序 fun.apply(this, rest); // 设置时间范围 active = true; setTimeout(()=> { active = false; }, t); } } }
example
function fun(a, b) { console.log(a + b); } const newPrint = Throttle(fun, 3000); newPrint('hello', 'world');
带返回值的封装封装
全局变量模式
/** * 声明 运行变量 * @type {boolean} */ let active; /** * 节流函数 * @param {function} fun 要执行的回调函数 * @param {number} t 时间差 * @param {...any} rest 回调函数所需参数 */ function Throttle(fun, t = 500, ...rest) { return new Promise((resolve, reject) => { // 在时间范围外 if (!active) { // 运行应用程序 resolve(fun.apply(this, rest)); // 设置时间范围 active = true; setTimeout(()=> { active = false; }, t); } else { reject('within protection time!'); } }) }
Example
function add(a, b) { return a + b; } Debounce(add, 3000)('1', '2').then(res => { console.log('res:', res); })
闭包模式
/** * 节流函数 * @param {function} fun 要执行的回调函数 * @param {number} t 时间差 * @returns {function} 返回函数 */ function Throttle(fun, t = 500) { let active; return function(...rest) { return new Promise((resolve, reject) => { // 在时间范围外 if (!active) { // 运行应用程序 resolve(fun.apply(this, rest)); // 设置时间范围 active = true; setTimeout(()=> { active = false; }, t); } else { reject('within protection time!'); } }) } }
example
function fun(a, b) { return a + b; } const print = Debounce(fun, 3000); // promise then回调函数 print('1', '2').then(res => { console.log('res:', res); }) // await let res = await print('1', '2'); console.log(res);
Thanks!