Debounce
import 'dart:async' show Timer;
import 'dart:math' as math;
const _undefined = Object();
class Debounce {
Debounce(
this._func,
Duration wait, {
bool leading = false,
bool trailing = true,
Duration? maxWait,
}) : _leading = leading,
_trailing = trailing,
_wait = wait.inMilliseconds,
_maxing = maxWait != null {
if (_maxing) {
_maxWait = math.max(maxWait!.inMilliseconds, _wait);
}
}
final Function _func;
final bool _leading;
final bool _trailing;
final int _wait;
final bool _maxing;
int? _maxWait;
Object? _lastArgs = _undefined;
Object? _lastNamedArgs = _undefined;
Timer? _timer;
int? _lastCallTime;
Object? _result;
int _lastInvokeTime = 0;
Object? _invokeFunc(int time) {
final args = _lastArgs as List<Object?>?;
final namedArgs = _lastNamedArgs as Map<Symbol, Object?>?;
_lastInvokeTime = time;
_lastArgs = _lastNamedArgs = _undefined;
return _result = Function.apply(_func, args, namedArgs);
}
Timer _startTimer(Function pendingFunc, int wait) =>
Timer(Duration(milliseconds: wait), () => pendingFunc());
bool _shouldInvoke(int time) {
if (_lastCallTime == null) return true;
final timeSinceLastCall = time - _lastCallTime!;
final timeSinceLastInvoke = time - _lastInvokeTime;
return (timeSinceLastCall >= _wait) ||
(timeSinceLastCall < 0) ||
(_maxing && timeSinceLastInvoke >= _maxWait!);
}
Object? _trailingEdge(int time) {
_timer = null;
if (_trailing &&
(_lastArgs != _undefined || _lastNamedArgs != _undefined)) {
return _invokeFunc(time);
}
_lastArgs = _lastNamedArgs = _undefined;
return _result;
}
int _remainingWait(int time) {
final timeSinceLastCall = time - _lastCallTime!;
final timeSinceLastInvoke = time - _lastInvokeTime;
final timeWaiting = _wait - timeSinceLastCall;
return _maxing
? math.min(timeWaiting, _maxWait! - timeSinceLastInvoke)
: timeWaiting;
}
void _timerExpired() {
final time = DateTime.now().millisecondsSinceEpoch;
if (_shouldInvoke(time)) {
_trailingEdge(time);
} else {
_timer = _startTimer(_timerExpired, _remainingWait(time));
}
}
Object? _leadingEdge(int time) {
_lastInvokeTime = time;
_timer = _startTimer(_timerExpired, _wait);
return _leading ? _invokeFunc(time) : _result;
}
void cancel() {
_timer?.cancel();
_lastInvokeTime = 0;
_lastCallTime = _timer = null;
_lastArgs = _lastNamedArgs = _undefined;
}
Object? flush() {
final now = DateTime.now().millisecondsSinceEpoch;
return _timer == null ? _result : _trailingEdge(now);
}
bool get isPending => _timer != null;
Object? call([List<Object?>? args, Map<Symbol, Object?>? namedArgs]) {
final time = DateTime.now().millisecondsSinceEpoch;
final isInvoking = _shouldInvoke(time);
_lastArgs = args;
_lastNamedArgs = namedArgs;
_lastCallTime = time;
if (isInvoking) {
if (_timer == null) {
return _leadingEdge(_lastCallTime!);
}
if (_maxing) {
_timer = _startTimer(_timerExpired, _wait);
return _invokeFunc(_lastCallTime!);
}
}
_timer ??= _startTimer(_timerExpired, _wait);
return _result;
}
}
Throttle
import "./debounce.dart";
class Throttle {
Throttle(
Function func,
Duration wait, {
bool leading = true,
bool trailing = true,
}) : _debounce = Debounce(
func,
wait,
leading: leading,
trailing: trailing,
maxWait: wait,
);
final Debounce _debounce;
void cancel() => _debounce.cancel();
Object? flush() => _debounce.flush();
bool get isPending => _debounce.isPending;
Object? call(List<Object?> args, [Map<Symbol, Object?>? namedArgs]) {
return _debounce.call(args, namedArgs);
}
}
extension DebounceThrottle on Function
import "./debounce.dart";
import "./throttle.dart";
extension DebounceThrottle on Function {
Debounce debounce(
Duration wait, {
bool leading = false,
bool trailing = true,
Duration? maxWait,
}) {
return Debounce(
this,
wait,
leading: leading,
trailing: trailing,
maxWait: maxWait,
);
}
Throttle throttle(
Duration wait, {
bool leading = true,
bool trailing = true,
}) {
return Throttle(
this,
wait,
leading: leading,
trailing: trailing,
);
}
}
Debounce debounce(
Function func,
Duration wait, {
bool leading = false,
bool trailing = true,
Duration? maxWait,
}) =>
Debounce(
func,
wait,
leading: leading,
trailing: trailing,
maxWait: maxWait,
);
Throttle throttle(
Function func,
Duration wait, {
bool leading = true,
bool trailing = true,
}) =>
Throttle(func, wait, leading: leading, trailing: trailing);
什么是function call / dart
lodash.com/docs/4.17.1…
pub.dev/packages/ra…