你一定看得懂的「函数防抖」&「函数节流」

image-20220304230326643

函数防抖(debounce)

  • 问:

    • 啥是函数防抖啊 ?有啥用啊 ?
  • 答:

    • 有的时候,一个函数有可能在很小的一个时间段内被频繁触发(比如双十一疯狂点击抢购按钮的时候),这会给整个系统造成不小的压力

    • 所以我们希望:只有当其中任意相邻两次触发之间的时间间隔达到一定长度,函数才会被执行一次,这就叫函数防抖

举个例子

  • 日常生活中我们赶公交,都希望赶得上吧 ?

  • 我们这里用代码模拟一下一旦有人上车,就立马发车的司机

1
2
3
4
5
6
7
8
9
function kaiChe() {
console.log('车开走了~');
}

// 车门
var door = document.getElementById('ipt');

// 一旦有人上车,就立马发车
door.oninput = kaiChe;
  • 大家应该这辈子也不想碰见这种司机..

  • 既然如此就从我做起,做一名全心全意为乘客着想的好司机 !

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 准备一个秒表
var clock;

function kaiChe() {
// 将表清零
clearTimeout(clock);
// 10 秒内没人上车再发车
clock = setTimeout(() => {
kaiChe();
}, 10000);
}

var door = document.getElementById('ipt');
door.oninput = kaiChe;
  • 但是我们没必要每次都是等待 10 秒钟,而且也并非只有在开公交的时候需要等人

  • 所以我们可以将这种等待再执行的操作抽象出来封装成函数,更具有通用性

1
2
3
4
// 期望的调用方式

door.oninput = debounce(kaiChe, 4000); // 4 秒之内无人上车再开车
me.onplan = debounce('睡懒觉', '周六'); // 我计划等到周六睡懒觉嘿嘿嘿
1
2
3
4
5
6
7
function debounce(fn, delay) {
var clock;
return function () {
clearTimeout(clock);
clock = setTimeout(fn, delay);
}
}

函数节流(throttle)

  • 问:

    • 啥是函数节流啊 ?有啥用啊 ?
  • 答:

    • 有的时候,一个函数有可能在很小的一个时间段内被频繁触发(比如双十一疯狂点击抢购按钮的时候),这会给整个系统造成不小的压力

    • 所以我们希望:只有当时间累积到一定程度,函数才允许被执行一次,这就叫函数节流

举个例子

  • 其实函数节流就像日常生活中一个没拧紧的,在一滴一滴地滴水的水龙头

  • 我们先用代码模拟一下:敲一下水龙头就立刻滴下一滴水的情景

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 取一个水桶
var oShuiTong = document.getElementById('shuitong');

// 滴水函数
function diShui() {
// 水桶中增加一滴水
oShuiTong.innerText = parseInt(oShuiTong.innerText) + 1;
}

// 一个神奇的水龙头
var oLongTou = document.getElementById('longtou');

// 敲一下水龙头就滴下一滴水
oLongTou.onclick = diShui;
  • 众所周知生活中处处皆有熊孩子,如果让他们发现这么神奇的水龙头,恰好该熊孩子又天赋异禀,一瞬间可以敲击 1000 下水龙头!
1
2
3
for (var i = 0; i < 1000; i ++) {
oLongTou.click();
}
  • 水桶中瞬间多了一瓢水。。这也太可怕了

  • 所以我们回归现实,水龙头上只有累积一定的水量,才能滴下一滴水

  • 这种每隔一定的时间才会执行一次的操作可以抽象出来封装为函数,更具通用性

1
2
// 期望的调用方式(eg:水龙头一秒钟滴下一滴水)
oLongTou.onclick = throttle(diShui, 1000);
1
2
3
4
5
6
7
8
9
10
function throttle(fn, waitTime) {
var lastTime = 0;
return function () {
var nowTime = new Date().getTime();
if (nowTime - lastTime > waitTime) {
fn();
lastTime = nowTime;
}
}
}

(完)