throttleFuture<T> method
针对future的节流 推荐在无参数输入的场景下使用
Implementation
Future<T> throttleFuture<T>({
Duration? duration,
List<Object?> positionalArgs = const [],
Map<Symbol, Object?> namedArgs = const {},
}) {
late final String key;
if (positionalArgs.isEmpty && namedArgs.isEmpty) {
key = this.hashCode.toString();
} else {
final keyBuffer = StringBuffer();
keyBuffer.write(this.hashCode);
for (final arg in positionalArgs) {
keyBuffer.write('_');
keyBuffer.write(arg.hashCode);
}
for (final entry in namedArgs.entries) {
keyBuffer.write('_');
keyBuffer.write(entry.key.hashCode);
keyBuffer.write('_');
keyBuffer.write(entry.value.hashCode);
}
key = keyBuffer.toString();
}
final now = DateTime.now();
final cached = ThrottleUtil.instance.throttleCache[key];
if (cached != null) {
if (cached.pendingFuture != null) {
return cached.pendingFuture as Future<T>;
}
if (duration != null && cached.completedFuture != null) {
if (now.difference(cached.lastCall) < duration) {
return cached.completedFuture as Future<T>;
}
}
}
final completer = Completer<T>();
final future = Function.apply(this, positionalArgs, namedArgs) as Future<T>;
future
.then((value) {
if (!completer.isCompleted) completer.complete(value);
ThrottleUtil.instance.throttleCache[key] = _ThrottleData<T>(
lastCall: now,
completedFuture: Future.value(value),
pendingFuture: null,
pendingCompleter: null,
);
return value;
})
.catchError((error) {
if (!completer.isCompleted) completer.completeError(error);
ThrottleUtil.instance.throttleCache.remove(key);
throw error;
});
ThrottleUtil.instance.throttleCache[key] = _ThrottleData<T>(
lastCall: now,
completedFuture: null,
pendingFuture: future,
pendingCompleter: completer,
);
return completer.future;
}