Skip to content

Commit e3aa552

Browse files
perf: support function's debounce and throttle
1 parent cb9daca commit e3aa552

2 files changed

Lines changed: 75 additions & 0 deletions

File tree

home_guardian/common/__init__.py

Whitespace-only changes.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import asyncio
2+
from time import time
3+
4+
5+
class Setter:
6+
def __init__(self, initial_value=None) -> None:
7+
self._value = initial_value
8+
9+
def get(self):
10+
return self._value
11+
12+
def set(self, v):
13+
self._value = v
14+
15+
16+
def debounce(delay):
17+
"""
18+
Debounce decorator.
19+
20+
@see Python 中的防抖与节流 https://www.bilibili.com/read/cv13257868
21+
"""
22+
23+
# 用于存储 asyncio.Task 实例,这里是闭包
24+
task = Setter()
25+
26+
def decorator(fn):
27+
# Task 协程函数
28+
async def f(*args, **kwargs):
29+
# 进行休眠
30+
await asyncio.sleep(delay)
31+
# 调用函数
32+
f1 = fn(*args, **kwargs)
33+
# 支持回调函数是异步函数的情况
34+
if asyncio.iscoroutine(f1):
35+
await f1
36+
# 清除 task
37+
task.set(None)
38+
39+
def wrapper(*args, **kwargs):
40+
# 如果 task 存在,说明在 delay 秒内调用过一次函数,此次调用应当重置计时器,因此取消先前的 Task
41+
if task.get() is not None:
42+
task.get().cancel()
43+
# 创建 Task 并赋值变量 task
44+
task.set(asyncio.create_task(f(*args, **kwargs)))
45+
46+
return wrapper
47+
48+
return decorator
49+
50+
51+
def throttle(delay):
52+
"""
53+
Throttle decorator.
54+
55+
@see Python 中的防抖与节流 https://www.moyu.moe/articles/25/
56+
"""
57+
58+
# 下一次许可调用的时间,初始化为 0
59+
next_t = Setter(0)
60+
61+
def decorator(fn):
62+
def wrapper(*args, **kwargs):
63+
# 当前时间
64+
now = time()
65+
# 若未到下一次许可调用的时间,直接返回
66+
if next_t.get() > now:
67+
return
68+
# 更新下一次许可调用的时间
69+
next_t.set(now + delay)
70+
# 调用函数并返回
71+
return fn(*args, **kwargs)
72+
73+
return wrapper
74+
75+
return decorator

0 commit comments

Comments
 (0)