It's fairly straightforward to make a helper function that measures the amount of time taken by the API call and then adds an appropriate delay before returning the result:
Future<R> callWithMinimumDuration<R>(
Future<R> Function() func,
Duration minimumDuration,
) async {
var stopwatch = Stopwatch()..start();
var result = await func();
var delta = minimumDuration - stopwatch.elapsed;
if (delta > Duration.zero) {
await Future.delayed(delta);
}
return result;
}
And then you'd invoke it with:
var result = await callWithMinimumDuration(apiCall, Duration(milliseconds: 1500));
Alternatively, you could use Future.wait
to combine the original Future
with a Future.delayed
. However, Future.wait
wants Future
s with homegeneous types, so you'd either need casts (whether explicit or implicit, if implicit dynamic
casts are allowed):
Future<R> callWithMinimumDuration<R>(
Future<R> Function() func,
Duration minimumDuration,
) async =>
(await Future.wait<Object?>([func(), Future.delayed(minimumDuration)]))[0]
as R;
or use an assignment technique to deal with heterogeneous Future
s:
Future<R> callWithMinimumDuration<R>(
Future<R> Function() func,
Duration minimumDuration,
) async {
late R result;
await Future.wait([
() async {
result = await func();
}(),
Future.delayed(minimumDuration),
]);
return result;
}
You also could use one of the .wait
extensions, but proper error-handling would be a bit more work:
Future<R> callWithMinimumDuration<R>(
Future<R> Function() func,
Duration minimumDuration,
) async {
try {
return (await (func(), Future.delayed(minimumDuration)).wait).$1;
} on ParallelWaitError catch (e, st) {
Error.throwWithStackTrace(e.errors.$1, st);
}
}