run<T> method
Implementation
Future<T?> run<T>(Future<T> Function() action) async {
final startTime = DateTime.now();
if (!enabled) {
_debugLog('AsyncDebounce bypassed (disabled)');
try {
final result = await action();
final executionTime = DateTime.now().difference(startTime);
onMetrics?.call(executionTime, false);
return result;
} catch (e) {
if (resetOnError) {
_debugLog('Error occurred, state reset');
}
rethrow;
}
}
_timer?.cancel();
// Cancel previous pending call
if (_pendingCompleter != null && !_pendingCompleter!.isCompleted) {
_pendingCompleter!.complete(null);
_debugLog('AsyncDebounce cancelled previous call');
final cancelTime = DateTime.now().difference(startTime);
onMetrics?.call(cancelTime, true);
}
final currentCallId = ++_latestCallId;
final completer = Completer<T?>();
_pendingCompleter = completer;
_timer = _timerFactory.createTimer(duration, () async {
try {
if (currentCallId != _latestCallId) {
if (!completer.isCompleted) {
completer.complete(null);
_debugLog('AsyncDebounce cancelled during wait');
}
return;
}
_debugLog('AsyncDebounce executing async action');
try {
final result = await action();
if (currentCallId == _latestCallId && !completer.isCompleted) {
final executionTime = DateTime.now().difference(startTime);
_debugLog(
'AsyncDebounce completed in ${executionTime.inMilliseconds}ms');
onMetrics?.call(executionTime, false);
completer.complete(result);
} else if (!completer.isCompleted) {
_debugLog('AsyncDebounce cancelled after execution');
completer.complete(null);
}
} catch (e, stackTrace) {
_debugLog('AsyncDebounce error: $e');
if (resetOnError) {
_debugLog('Resetting AsyncDebouncer state due to error');
cancel();
}
if (!completer.isCompleted) {
completer.completeError(e, stackTrace);
}
}
} catch (e, stackTrace) {
if (!completer.isCompleted) {
completer.completeError(e, stackTrace);
}
} finally {
if (_pendingCompleter == completer) {
_pendingCompleter = null;
}
}
});
return completer.future;
}