runZoned<R> function

R runZoned <R>(R body(), { Map zoneValues, ZoneSpecification zoneSpecification, Function onError })

Runs body in its own zone.

Returns the result of invoking body.

If onError is non-null the zone is considered an error zone. All uncaught errors, synchronous or asynchronous, in the zone are caught and handled by the callback. When the error is synchronous, throwing in the onError handler, leads to a synchronous exception.

Returns null when body threw, and a provided onError function completed without throwing.

Errors may never cross error-zone boundaries. This is intuitive for leaving a zone, but it also applies for errors that would enter an error-zone. Errors that try to cross error-zone boundaries are considered uncaught.

var future = new Future.value(499);
runZoned(() {
  future = future.then((_) { throw "error in first error-zone"; });
  runZoned(() {
    future = future.catchError((e) { print("Never reached!"); });
  }, onError: (e) { print("unused error handler"); });
}, onError: (e) { print("catches error of first error-zone."); });

Example:

runZoned(() {
  new Future(() { throw "asynchronous error"; });
}, onError: print);  // Will print "asynchronous error".

Implementation

R runZoned<R>(R body(),
    {Map zoneValues, ZoneSpecification zoneSpecification, Function onError}) {
  // TODO(floitsch): the return type should be `void` here.
  if (onError != null &&
      onError is! ZoneBinaryCallback<dynamic, Object, StackTrace> &&
      onError is! ZoneUnaryCallback<dynamic, Object>) {
    throw new ArgumentError("onError callback must take an Object (the error), "
        "or an Object (the error) and a StackTrace");
  }
  HandleUncaughtErrorHandler errorHandler;
  if (onError != null) {
    errorHandler = (Zone self, ZoneDelegate parent, Zone zone, error,
        StackTrace stackTrace) {
      try {
        if (onError is void Function(Object, StackTrace)) {
          self.parent.runBinary(onError, error, stackTrace);
          return;
        }
        assert(onError is void Function(Object));
        self.parent.runUnary(onError, error);
      } catch (e, s) {
        if (identical(e, error)) {
          parent.handleUncaughtError(zone, error, stackTrace);
        } else {
          parent.handleUncaughtError(zone, e, s);
        }
      }
    };
  }
  if (zoneSpecification == null) {
    zoneSpecification =
        new ZoneSpecification(handleUncaughtError: errorHandler);
  } else if (errorHandler != null) {
    zoneSpecification = new ZoneSpecification.from(zoneSpecification,
        handleUncaughtError: errorHandler);
  }
  Zone zone = Zone.current
      .fork(specification: zoneSpecification, zoneValues: zoneValues);
  if (onError != null) {
    try {
      return zone.run(body);
    } catch (e, stackTrace) {
      if (onError is ZoneBinaryCallback<R, Object, StackTrace>) {
        zone.runBinary(onError, e, stackTrace);
        return null;
      }
      assert(onError is ZoneUnaryCallback<R, Object>);
      zone.runUnary(onError, e);
      return null;
    }
  } else {
    return zone.run(body);
  }
}