runWithTimeout<T> static method
Executes a function with a timeout.
If the timeout elapses first, the returned future completes with a TimeoutException. The original task continues to execute in the background, and any errors it throws after the timeout are handled internally to avoid unhandled asynchronous exceptions.
Implementation
static Future<T> runWithTimeout<T>({
required FutureOr<T> Function() task,
required Duration timeout,
}) {
final completer = Completer<T>();
Timer? timeoutTimer;
timeoutTimer = Timer(timeout, () {
if (!completer.isCompleted) {
completer.completeError(
TimeoutException('The operation has timed out.'),
);
}
});
final taskFuture = Future<T>.sync(task);
taskFuture.then((value) {
if (!completer.isCompleted) {
timeoutTimer?.cancel();
completer.complete(value);
}
}).catchError((error, stackTrace) {
if (!completer.isCompleted) {
timeoutTimer?.cancel();
completer.completeError(error, stackTrace);
}
// Once the completer finished because the timeout elapsed, swallow
// remaining errors to keep the zone clean.
});
return completer.future.whenComplete(() => timeoutTimer?.cancel());
}