用一张图片来解释

防抖 debounce

在第一次触发函数时,不立刻触发函数,而是给一个时间,如果在这个时间内多次触发函数,只执行一次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function debounce(fn, delay) {
// 需要在return外部声明timer
// 多次触发debounce的时候,return的函数共享一个timer变量
let timer;
return function () {
// 保存this
let context = this;
// 保存传入的参数
let args = arguments;
clearTimeout(timer);
timer = setTimeout(function () {
// 改变this指向,并传入参数
fn.apply(context, args);
}, delay);
};
}

防止重复发送请求

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
class debounceXhr {
constructor() {
this.ajaxXhr = null;
}
sendData() {
if (this.ajaxXhr) return;
this.ajaxXhr = new Promise((resolve, reject) => {
ajax({
url: "/api",
data: "data",
success(res) {
if (res.message == "success") {
resolve(res);
} else {
reject(res);
}
},
error(err) {
reject(err);
},
complete() {
this.ajaxXhr = null;
},
});
});
}
}

节流 throttle

在限定时间内只执行一次函数

使用 setTimeout 实现节流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function throttle(fn, delay) {
let timer;
return function () {
let context = this;
let args = arguments;
if (timer) {
return;
}
timer = setTimeout(function () {
fn.apply(context, args);
timer = null;
}, delay);
};
}

使用时间戳实现节流

1
2
3
4
5
6
7
8
9
10
11
12
function throttle(fn, delay) {
let pre = 0;
return function () {
let now = new Date();
let context = this;
let args = arguments;
if (now - pre > delay) {
fn.apply(context, args);
pre = now;
}
};
}