防抖与节流

  • 防抖:当连续调用时间间隔小于delay时,只执行最后一次调用
  • 节流:某段时间内多次调用,只生效第一次,(限制某段时间内的调用次数,次数为1且是第一次)
  • 参考文章
  • 目的: 优化一个被频繁调用/触发的函数/事件
  • 防抖应用:比如当用户在快速输入时,不应每次输入都调用请求,而是当用户一定时间内未再输入,再调用请求
  • 节流应用:比如限制用户的调用请求,避免用户快速点击请求的时候,频繁向后台发送请求,而是第一次调用后,再间隔一定时间后才能继续调用下一次。
  • ts中可以使用装饰器Decorators修饰函数,使其成为防抖/节流函数

防抖#

Vue自定义防抖ref#

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
<template>
<h1>自定义防抖ref</h1>
<input v-model="text" />
<div>{{ text }}</div>
</template>
<script setup lang="ts">
import { customRef } from 'vue';
/**
* 自定义防抖ref
* @param value 值
* @param delay 延迟时间, 默认500ms
*/
function debounceRef(value: any, delay:number = 500){
let timer: number;
// customRef 的参数是一个函数, 其参数有track和trigger两个, 返回一个带有get,set的对象
return customRef((track, trigger) => {
return {
get() {
track();
return value;
},
set(newVal: any) {
clearTimeout(timer);
// timer赋值
timer = setTimeout(() => {
value = newVal;
trigger();
}, delay)
}
}
})
}
const text = debounceRef('');
</script>

防抖装饰器#

1
2
3
4
5
6
7
8
9
10
// ts
export default (fun: Function, delay: number = 500) => {
let timer: number;
return function (this: unknown, ...args: any[]) {
clearTimeout(timer);
timer = setTimeout(() => {
fun.apply(this, args)
}, delay)
}
}
1
2
3
4
5
6
7
8
9
10
// js
function debounce(fun, delay = 500) {
let timer = null;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => {
fun.apply(this, args)
}, delay)
}
}

节流#

Lodash: https://www.lodashjs.com/docs/lodash.throttle#_throttlefunc-wait0-options

Lodash节流函数源码: https://github.com/lodash/lodash/blob/master/throttle.js

现代JS教程: https://zh.javascript.info/task/throttle

1
2
3
4
5
6
7
8
9
10
11
function throttle(func, wait=1000) {
let timer = null;
return function(...args) {
if (!timer) {
timer = setTimeout(() => {
func.apply(this, args);
timer = null;
}, wait);
}
};
}