简单弄懂防抖与节流~

1,106 阅读4分钟

今天来介绍一下防抖(debounce)节流(throttle),相信大家对这俩词肯定不陌生,今天主要是希望可以用最简单的方式帮大家弄懂防抖和节流, 那我们直接进入主题吧~~

概念介绍

首先来看一下,防抖(debounce)节流(throttle)的概念.

函数防抖debounce

  1. 概念: 事件停止触发指定时间后再执行函数,如果在这时间又被触发,则不触发重新计时.
  2. 举例: 开始拖动地图,设定1000ms后触发请求数据,如果在1000ms内我停止拖动了,则直接请求数据,如果1000ms内我再次触发拖动事件,则重新计时,不触发请求.

函数节流throttle:

  1. 概念: 在指定的时间间隔内,一定会只执行一次函数
  2. 举例: 开始拖动地图,设定500ms后触发请求数据,在500ms内无论我停止还是继续拖动,到500ms时就会触发一次.

场景介绍

函数防抖debounce

  1. 搜索: 最常见的就input,不断输入,会导致不断的请求,可以用防抖来节约请求资源.
  2. resize: 当我们不断的调整浏览器窗口大小的时候,会不断的触发resize事件,可以用防抖来控制其触发次数
  3. 地图拖动: 拖动过程中,需要加载当前可视窗覆盖物数据,如果不停拖动,会触发多次请求,导致地图卡顿,可以用防抖来控制请求次数

函数节流throttle:

  1. 鼠标点击: 不断点击会导致不断触发,可以用节流控制其指定时间内只触发一次
  2. 滚动事件: 页面数据过长,可以通过节流来控制滚动指定时间内加载一次数据

案例

input案例网上大把有,都写的挺好的,大家可以自行百度/Google, 我就以BMap拖动为例,分别用debouncethrottle的方式来实现

先来看一下,没有防抖节流的情况下,拖动地图时,请求的情况(请求触发的动作在这里用console.log代替)

const map = new BMapGL.Map('container');
map.centerAndZoom(new BMapGL.Point(116.404, 39.928), 15);
map.enableScrollWheelZoom(true);
// dragend: 停止拖拽地图时触发
map.addEventListener('dragend', (e: any) => {
    console.log('拖动停止触发', e.latlng);
});

来看下效果

从图中可以看到,拖动停止的时候就会触发请求,但是有时候,我们并没有拖动到目的地,但是手机屏幕可拖动的区域是有限的,必须要停止在继续拖动,这样其实是很浪费资源的,而且如果时间过长对性能也是有影响的,可见这并不是很好的方式.

防抖案例

首先我们用防抖的方式来解决这个问题,上代码:

// debounce.ts
const debounce = (func: Function, delay: number) => {
    let timer: any = null;
    // 接受函数的所有参数
    return (...args: any[]) => {
        clearTimeout(timer);
        timer = setTimeout(() => {
            func(...args);
            timer = null;
        }, delay);
    };
};

// 调用
const map = new BMapGL.Map('container');
map.centerAndZoom(new BMapGL.Point(116.404, 39.928), 15);
map.enableScrollWheelZoom(true);

const debounceGet = debounce((val: any) => {
	console.log('debounce-拖动地图', val.latlng);
}, 1000);
map.addEventListener('dragend', (e: any) => {
    debounceGet(e);
});

来看下效果

从图中可以看到,并不是在我们每次拖动停止的时候就请求数据,当拖动停止后1000ms就会去请求数据,如果1000ms内还保持拖动的状态,是不会请求数据的.

节流案例

首先我们用节流的方式来解决这个问题,上代码:

// throttle.ts
const throttle = (func: Function, delay: number) => {
    let last = 0;
    let timer: any = null;
    return (...args: any[]) => {
        const curr = new Date().getTime();
        clearTimeout(timer);
        if (last && curr - last >= delay) {
            func(...args);
            last = curr;
        } else {
            timer = setTimeout(() => {
                func(...args);
                last = curr;
            }, delay);
        }
    };
};

// 调用
const map = new BMapGL.Map('container');
map.centerAndZoom(new BMapGL.Point(116.404, 39.928), 15);
map.enableScrollWheelZoom(true);

const throttleGet = throttle((val: any) => {
    console.log('throttle-拖动地图', val.latlng);
}, 1000);
map.addEventListener('dragend', (e: any) => {
    throttleGet(e);
});

来看下效果

从图中可以看到,并不是在我们每次拖动停止的时候就请求数据,但是拖动过程中,每1000ms就会去请求一次数据.

以上就是防抖和节流的全部内容了,大家在实际开发过程中可以根据需求决定使用哪种,希望本文对大家有所帮助~

关注UU

关注公众号【前端UU】, 定期获取好文推荐哟~