runZonedGuarded<R> function

  1. @Since("2.8")
R? runZonedGuarded<R>(
  1. R body(),
  2. void onError(
    1. Object error,
    2. StackTrace stack
    ), {
  3. Map<Object?, Object?>? zoneValues,
  4. ZoneSpecification? zoneSpecification,
})

Runs body in its own error zone.

Creates a new zone using Zone.fork based on zoneSpecification and zoneValues, then runs body in that zone and returns the result.

The onError function is used both to handle asynchronous errors by overriding ZoneSpecification.handleUncaughtError in zoneSpecification, if any, and to handle errors thrown synchronously by the call to body.

If an error occurs synchronously in body, then throwing in the onError handler makes the call to runZonedGuarded throw that error, and otherwise the call to runZonedGuarded returns null.

The created zone will always be an error zone. Asynchronous errors in futures never cross zone boundaries between zones with a different Zone.errorZone. A consequence of that behavior can be that a Future which completes as an error in the created zone will seem to never complete when used from a zone that belongs to a different error zone. Multiple attempts to use the future in a zone where the error is inaccessible will cause the error to be reported again in it's original error zone.

Implementation

@Since("2.8")
R? runZonedGuarded<R>(
  R body(),
  void onError(Object error, StackTrace stack), {
  Map<Object?, Object?>? zoneValues,
  ZoneSpecification? zoneSpecification,
}) {
  _Zone parentZone = Zone._current;
  HandleUncaughtErrorHandler errorHandler = (
    Zone self,
    ZoneDelegate parent,
    Zone zone,
    Object error,
    StackTrace stackTrace,
  ) {
    try {
      parentZone.runBinary(onError, error, stackTrace);
    } catch (e, s) {
      if (identical(e, error)) {
        parent.handleUncaughtError(zone, error, stackTrace);
      } else {
        parent.handleUncaughtError(zone, e, s);
      }
    }
  };
  if (zoneSpecification == null) {
    zoneSpecification = ZoneSpecification(handleUncaughtError: errorHandler);
  } else {
    zoneSpecification = ZoneSpecification.from(
      zoneSpecification,
      handleUncaughtError: errorHandler,
    );
  }
  try {
    return _runZoned<R>(body, zoneValues, zoneSpecification);
  } catch (error, stackTrace) {
    onError(error, stackTrace);
  }
  return null;
}