18

There is a special function runZoned provided by dart:async. The document is here: https://api.dartlang.org/docs/channels/stable/latest/dart_async.html#runZoned

I'm not sure what's the purpose of this function, when will we need it, and how to use it properly?

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
Freewind
  • 193,756
  • 157
  • 432
  • 708
  • 1
    This feature was added to compensate the lack of other useful features. It only useful if you need (want?) catch error in the code that you cannot modify. That is, it useful if you want work with code that throw unexptected exception in asynchronous operations. The `runZoned` can trapping these unobserved exceptions that you cannot catch by some reason due the errors in that source code. As for me, it is better not use code that throw unobserved exceptions than run this code with known bugs in `runZoned` environment. Lack of other useful features: async/await – mezoni Feb 03 '14 at 16:33
  • 2
    When compiler support `async / await` operations it (or other tool) can detect potential mistakes in source code with asynchronous operations. In this case it can generate the warnings for programmers. In this case `runZoned` not so often needed if program written with the conventions of `async/await` operations programming and do not contains obvious potential mistakes that can lead to unobserved exceptions. In fact, `runZoned` are `forced` trap for missed (unobserved) exeptions in asynchronous code, which are physically impossible to catch due to improperly written source code. – mezoni Feb 03 '14 at 16:53

1 Answers1

18

Look at this code:

import 'dart:async';

void main() {
  fineMethod().catchError((s) {}, test : (e) => e is String);
  badMethod().catchError((s) {}, test : (e) => e is String);
}

Future fineMethod() {
  return new Future(() => throw "I am fine");
}

Future badMethod() {
  new Future(() => throw "I am bad");
  return new Future(() => throw "I am fine");
}

Output

Unhandled exception:
I am bad

Now look at this code:

import 'dart:async';

void main() {
  fineMethod().catchError((s) {}, test : (e) => e is String);

  runZoned(() {
    badMethod().catchError((s) {}, test : (e) => e is String);
  }, onError : (s) {
    print("It's not so bad but good in this also not so big.");
    print("Problem still exists: $s");
  });
}

Future fineMethod() {
  return new Future(() => throw "I am fine");
}

Future badMethod() {
  new Future(() => throw "I am bad");
  return new Future(() => throw "I am fine");
}

Output

It's not so bad but good in this also not so big.
Problem still exists: I am bad

You should strictly avoid using badMethod if this possible.

Only if this not possible you may temporary use runZoned

Also you may use runZoned to simulate sandboxed execution of tasks.

Updated version of the answer:

import 'dart:async';

Future<void> main() async {
  try {
    await fineMethod();
  } catch (e) {
    log(e);
  }

  await runZonedGuarded(() async {
    try {
      await badMethod();
    } catch (e) {
      log(e);
    }
  }, (e, s) {
    print("========");
    print("Unhandled exception, handled by `runZonedGuarded`");
    print("$e");
    print("========");
  });
}

Future badMethod() {
  // Unhandled exceptions
  Future(() => throw "Bad method: bad1");
  Future(() => throw "Bad method: bad2");
  return Future(() => throw "Bad method: fine");
}

Future fineMethod() {
  return Future(() => throw "Fine method: fine");
}

void log(e) {
  print('Handled exception:');
  print('$e');
}

Output:

Handled exception:
Fine method: fine
========
Unhandled exception, handled by `runZonedGuarded`
Bad method: bad1
========
========
Unhandled exception, handled by `runZonedGuarded`
Bad method: bad2
========
Handled exception:
Bad method: fine
mezoni
  • 10,684
  • 4
  • 32
  • 54