timebox<T> function

Future<T> timebox<T>(
  1. Future<T> fn(),
  2. Duration timeout, {
  3. T? onTimeout,
})

Runs fn; if not completed in timeout, returns onTimeout result (or throws). Audited: 2026-06-12 11:26 EDT

Implementation

Future<T> timebox<T>(Future<T> Function() fn, Duration timeout, {T? onTimeout}) async {
  // Race fn() against a timer via a single Completer: whichever finishes first
  // wins, and the isCompleted guards make the loser a no-op (a Completer can be
  // completed only once).
  final Completer<T> c = Completer<T>();
  Timer? t;
  t = Timer(timeout, () {
    // Timer fired first: settle with the fallback if one was given, else fail.
    if (!c.isCompleted) {
      if (onTimeout != null) {
        c.complete(onTimeout);
      } else {
        c.completeError(TimeboxException(_kTimeboxExceeded), StackTrace.current);
      }
    }
  });
  try {
    final T result = await fn();
    if (!c.isCompleted) c.complete(result);
    return await c.future;
  } on Object catch (e, st) {
    developer.log('Timebox caught error', name: 'timebox', error: e);
    if (!c.isCompleted) c.completeError(e, st);
    rethrow;
  } finally {
    t.cancel();
  }
}