runWithTimeout<T> static method

Future<T> runWithTimeout<T>({
  1. required FutureOr<T> task(),
  2. required Duration timeout,
})

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());
}