前言
在开发中,我们经常会遇到需要频繁触发某个函数的情况,比如:
监听滚动条的变化,当滚动条的位置发生变化时,需要执行某个函数
监听鼠标的移动,当鼠标的位置发生变化时,需要执行某个函数
监听键盘的按键,当键盘的某个按键被按下时,需要执行某个函数
当用户频繁的与UI
界面操作交互时,例如:窗口调整
(触发resize),页面滚动
,上拉加载
(触发scroll),表单的按钮提交,商城抢购疯狂的点击(触发mousedown
),而实时的搜索(keyup
,input
),拖拽等
当你频繁的触发用户界面时,会不停的触发事件处理函数,换而言之,当出现连续点击,上拉加载,实时搜索,对DOM元素频繁操作,请求资源加载等耗性能的操作,可能导致界面卡顿,浏览器奔溃,页面空白等情况
而解决这一问题的,正是函数节流与函数防抖
函数节流
定义: 节约(减少)触发事件处理函数的频率,连续每隔一定的时间触发执行的函数,它是优化高频率执行一段js代码的一种手段
特点: 不管事件触发有多频繁,都会保证在规定的间隔时间内真正的执行一次事件处理函数,只会让一个函数在某个时间窗口内执行一次,若在时间窗口内再次触发,则重新计算时间
应用场景: 常用于鼠标连续多次点击click
事件,鼠标移动mousemove
,拖拽
,窗口尺寸改动
(resize),鼠标滚轮页面上拉
(onScroll),上拉刷新懒加载
原理: 通过判断是否达到一定的时间来触发函数,若没有规定时间则使用计时器进行延迟,而下一次事件则会重新设定计时器,它是间隔时间执行
通常与用户界面高频的操作有:
鼠标滚轮页面上拉(onScroll),下拉刷新懒加载
窗口尺寸改动(onresize)
拖拽
若是高频操作,若不进行一定的处理,必然会造成多次数据的请求,服务器的压力,这样代码的性能是非常低效的,影响性能,降低这种频繁操作的一个重要的手段,就是降低频率,通过节流控制,也就是让核心功能代码在一定的时间,隔多长时间内执行一次
节流就是保证一段时间内只执行一次核心代码
你可以联想生活中节约用水(三峡大坝设置很多水闸)的例子:
高频事件就像是一个大开的水龙头,水流源源不断的大量流出,就像代码在不断的执行,若不加以控制,就会造成资源的一种浪费 对应页面中的,若是表单中连续点击提交按钮,监听滚动事件,连续下拉加载等请求服务器的资源
要节流,拧紧水龙头,要它的流水频率降低,每隔一段时间滴一滴水的,从而节省资源
在代码中的体现就是:设置一定时器,让核心功能代码,隔间段的去执行
下面是一个鼠标滚轮,节流操作实现:类似连续操作的,都是如此,连续点击按钮,上拉加载
节流方式一:时间戳+定时器
/* throttle1函数,节流实现方式1:时间戳+定时器
* @params method,duration 第一个参数为事件触发时的真正要执行的函数
* 第二个参数duration表示为定义的间隔时间
*
* 原理:通过判断是否达到一定的时间来触发函数,若没有规定时间则使用计时器进行延迟,而下一次事件则会重新设定计时器,它是间隔时间执行,不管事件触发有多频繁,都会保证在规定内的事件一定会执行一次真正事件处理函数
*
* */
function throttle1(method, duration) {
var timer = null;
var prevTime = new Date(); // 之前的时间
return function() {
var that = this,
currentTime = new Date(), // 获取系统当前时间
resTime = currentTime - prevTime; // 时间戳
// 打印本次当前的世间和上次世间间隔的时间差
console.log("时间差", resTime);
// 当前距离上次执行时间小于设置的时间间隔
if(resTime < duration) {
// 清除上次的定时器,取消上次调用的队列任务,重新设置定时器。这样就可以保证500毫秒秒内函数只会被触发一次,达到了函数节流的目的
clearTimeout(timer);
timer = setTimeout(functio