修复防抖可以全部执行完成
This commit is contained in:
parent
c184721f06
commit
825aa8017d
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:easy_debounce/easy_debounce.dart';
|
import 'package:easy_debounce/easy_debounce.dart';
|
||||||
import 'package:easy_debounce/easy_throttle.dart';
|
import 'package:easy_debounce/easy_throttle.dart';
|
||||||
|
|
||||||
|
|
@ -15,6 +17,9 @@ class AsyncThrottle {
|
||||||
// 存储异步任务锁状态
|
// 存储异步任务锁状态
|
||||||
final Map<String, bool> _asyncLocks = {};
|
final Map<String, bool> _asyncLocks = {};
|
||||||
|
|
||||||
|
// 存储防抖模式下的 Completer,确保被取消的任务能正确结束 await
|
||||||
|
final Map<String, Completer<void>> _debounceCompleters = {};
|
||||||
|
|
||||||
/// 异步执行方法 - 防止弱网重复点击 (无 Loading UI)
|
/// 异步执行方法 - 防止弱网重复点击 (无 Loading UI)
|
||||||
///
|
///
|
||||||
/// 结合了 时间策略(防抖/节流)和 异步任务状态锁。
|
/// 结合了 时间策略(防抖/节流)和 异步任务状态锁。
|
||||||
|
|
@ -40,18 +45,37 @@ class AsyncThrottle {
|
||||||
|
|
||||||
if (enableDebounce) {
|
if (enableDebounce) {
|
||||||
// === 防抖模式 (Debounce) ===
|
// === 防抖模式 (Debounce) ===
|
||||||
// 延迟 duration 后执行,如果在期间再次调用,会重新计时
|
|
||||||
|
// 关键修复:检查是否有正在等待的防抖请求。
|
||||||
|
// 如果有,说明它被本次新请求“顶掉”了(EasyDebounce 会取消上一个 Timer)。
|
||||||
|
// 我们需要手动完成它,否则上一次的 await 将永远挂起,导致内存泄漏。
|
||||||
|
if (_debounceCompleters.containsKey(tagId)) {
|
||||||
|
_completeDebounce(tagId);
|
||||||
|
}
|
||||||
|
|
||||||
|
final completer = Completer<void>();
|
||||||
|
_debounceCompleters[tagId] = completer;
|
||||||
|
|
||||||
EasyDebounce.debounce(tagId, duration, () async {
|
EasyDebounce.debounce(tagId, duration, () async {
|
||||||
// 防抖触发时,再次检查锁(双重检查)
|
// 双重检查:确保 Completer 还在(防止极端并发情况)
|
||||||
if (isExecuting(tagId)) return;
|
if (!_debounceCompleters.containsKey(tagId)) return;
|
||||||
|
|
||||||
|
// 防抖触发时,再次检查锁
|
||||||
|
if (isExecuting(tagId)) {
|
||||||
|
_completeDebounce(tagId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_asyncLocks[tagId] = true;
|
_asyncLocks[tagId] = true;
|
||||||
try {
|
try {
|
||||||
await onExecute();
|
await onExecute();
|
||||||
} finally {
|
} finally {
|
||||||
_asyncLocks.remove(tagId);
|
_asyncLocks.remove(tagId);
|
||||||
|
_completeDebounce(tagId); // 任务结束,通知 await 返回
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await completer.future;
|
||||||
} else {
|
} else {
|
||||||
// === 节流模式 (Throttle) - 默认 ===
|
// === 节流模式 (Throttle) - 默认 ===
|
||||||
// 立即执行,并在 duration 内忽略后续调用
|
// 立即执行,并在 duration 内忽略后续调用
|
||||||
|
|
@ -71,9 +95,26 @@ class AsyncThrottle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 辅助方法:安全地完成并移除 Completer
|
||||||
|
void _completeDebounce(String tagId) {
|
||||||
|
if (_debounceCompleters.containsKey(tagId)) {
|
||||||
|
final completer = _debounceCompleters[tagId];
|
||||||
|
if (completer != null && !completer.isCompleted) {
|
||||||
|
completer.complete();
|
||||||
|
}
|
||||||
|
_debounceCompleters.remove(tagId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 检查任务是否正在执行
|
/// 检查任务是否正在执行
|
||||||
bool isExecuting(String tagId) => _asyncLocks[tagId] ?? false;
|
bool isExecuting(String tagId) => _asyncLocks[tagId] ?? false;
|
||||||
|
|
||||||
/// 强制取消所有锁(慎用)
|
/// 强制取消所有锁(慎用)
|
||||||
void clearAllLocks() => _asyncLocks.clear();
|
void clearAllLocks() {
|
||||||
|
_asyncLocks.clear();
|
||||||
|
// 清理时把所有等待的 Future 也都释放掉,防止外部 await 永久挂起
|
||||||
|
for (var key in _debounceCompleters.keys.toList()) {
|
||||||
|
_completeDebounce(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue