函数防抖和函数节流

引子

这是一篇 Tip 性的文章,主要是用来记录某些 JS 的小应用和小知识,这一篇主要是讲述平时常见的用户列表懒加载所用到的内在思想。

防抖(debounce)

  • 下达命令后,在 t 毫秒内再次下达该命令,则取消刚刚下达的命令,只执行新命令
  • 最终效果:对于连续动作(动作时间间隔小于 t),以最后一次为准

范例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 防抖
let command;

document.body.onscroll = () => {
console.log("这里每次都执行");
if (command) {
clearTimeout(command);
}

command = setTimeout(() => {
console.log("这里执行很少次");
}, 1000);
};

// 常用于滚动加载,例如用户滚动页面时,不做任何操作,当用户滚动停止时,才发送ajax请求,获取数据
// 原理:清除上一次添加的定时器,添加新的定时器

// -----------------------------------------------------------------
// 封装版
function debounce(fn, wait) {
let timer = null;
return function () {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(this, arguments);
}, wait);
};
}

// 调用

let fn = () => console.log("这里执行很少次");
fn = debounce(fn, 1000);

document.body.onscroll = fn;

节流(throttle)

  • 从上一次命令结束开始的一定时间范围 t 内,如果多次连续下达命令,则只执行当前时间段 t 内的第一次命令
  • 最终效果:对于连续动作,会过滤出部分动作,让这些过滤后的动作之间的间隔大于等于 t

范例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 节流
let gapTime = 1000;
let lastTime = null;
let nowTime = null;
let fn = () => [console.log("我执行了")];

document.body.onscroll = () => {
nowTime = Data.now();
if (!lastTime || nowTime - lastTime > gapTime) {
fn();
lastTime = nowTime;
}
};

// 每一秒只执行一次

// 封装版

function throttle(fn, gapTime) {
let lastTime = null;
let nowTime = null;
return function () {
nowTime = Data.now();
if (!lastTime || lastTime - nowTime > gapTime) {
fn();
lastTime = nowTime;
}
};
}

let fn = () => {
console.log("执行");
};

fn = throttle(fn, 1000);

document.body.onscroll = fn;

// 常见应用:自动保存,用户写文章
作者

bert_cai

发布于

2019-06-10

更新于

2020-11-16

许可协议

评论