防抖函数 Debounce
# 什么是防抖函数
debounce 防抖函数,常用于某方法短时间内多次调用,但却不需要多次响应的场景。例如搜索的时候需要调用后端接口展示数据,但是在输入阶段是逐字录入的,这时候会触发多次接口,实际上仅需要输入完后触发一次即可。或者按钮短时间内多次点击,仅需要响应一次的场景。
# 实现方式
防抖函数的实现思想并不复杂,下面提供了一个简单示例:
function debounce(func, wait) {
let timer;
return function() {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(func, wait);
};
};
const debounced = debounce(()=> console.log(123), 1000);
debounced()
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 思考
防抖函数在前端开发中经常使用,比如给事件绑定防抖函数或者绑定 DOM 事件。
<button @click="debounced"> 点击 </button>
1
所以我想,在服务端能不能用最小 demo,复现该效果。因此有了第一版 demo。
V1:
'use strict';
const http = require('http');
const host = '127.0.0.1';
const port = 7001;
const server = http.createServer((req, res) => {
console.log('request received');
function debounce(func, wait) {
let timer;
return function() {
console.log('timer', !!timer);
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(func, wait);
};
}
const debounced = debounce(() => console.log(123), 1000);
debounced();
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
});
server.listen(port, host, () => {
console.log('Server running as ', host, ':', port);
});
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
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
当前版本在运行后不符合预期,多次请求,并不能共享 timer。后来更改了一版。
V2:
'use strict';
const http = require('http');
const host = '127.0.0.1';
const port = 7001;
let timer;
const server = http.createServer((req, res) => {
console.log('request received');
function debounce(func, wait) {
return function() {
console.log('timer', !!timer);
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(func, wait);
};
}
const debounced = debounce(() => console.log(123), 1000);
debounced();
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
});
server.listen(port, host, () => {
console.log('Server running as ', host, ':', port);
});
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
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
timer 提成全局变量以后,确实达到了预期,但是明显与在前端中的实践略有不同。研究一番以后有了第三版。
V3:
'use strict';
const http = require('http');
const host = '127.0.0.1';
const port = 7001;
function debounce(func, wait) {
let timer;
return function() {
console.log('timer', !!timer);
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(func, wait);
};
}
const debounced = debounce(() => console.log(123), 1000);
const server = http.createServer((req, res) => {
console.log('request received');
debounced();
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
});
server.listen(port, host, () => {
console.log('Server running as ', host, ':', port);
});
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
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
第三版也符合预期,但是感觉还差点意思,毕竟类似于将 func 抽到了全局。并不像前端,可以在逻辑里,封一个 debounced func 供组件和 DOM 用。
比较好奇的地方是,每次点击事件的触发和每次请求,有什么差异。为什么在请求事件中封装 func,可以共享参数。而每次请求会生成新的 func?
编辑 (opens new window)
上次更新: 2024/01/04, 15:25:52