Вы попали в острый край зон фьючерсов и ошибок (-обработка).
Ошибка, выданная в одной зоне ошибок, не будет распространяться на будущий обработчик ошибок, созданный в другой зоне ошибок. Таким образом, если вы получаете будущее из другой зоны ошибок, и оно завершилось с ошибкой, то вы не можете получить ошибку, и нет значения для ее получения, поэтому будущее будет выглядеть так: никогда завершено.
Код
main(args) async {
await runZoned(() async {
await Future.error(false);
}, onError: (e) async {
print("working in onError");
await runZoned(() async {
await Future.error(false);
}, onError: (e) async {
print("error 1");
});
print("error 2");
});
print("finish");
}
приводит аргументы к runZone
в новых зонах ошибок. Это асинхронные функции, возвращающие фьючерсы, поэтому await Future.error(false)
сгенерирует и завершит возвращенное будущее с ошибкой в этой конкретной зоне ошибки.
Затем, когда runZoned
завершится, он вернет это будущее сошибка, созданная в другой зоне ошибки, чем при вызове. Это await
ed (в корневой зоне, которая является другой зоной ошибок), поэтому await runZoned(() async { ... }, ...)
никогда не завершает . await
ожидает завершения будущего, будущее отказывается сообщать слушателю ошибку, с которой оно завершилось, поэтому ничего не происходит.
Фактически вы ожидаете будущее, которое никогда не завершается, чтоВот почему ваша программа останавливается в этой точке.
Так что это работает как задумано - ошибка никогда не покидает зону ошибки, в которой она была создана, но оставляет внешнюю зону без какого-либо результата.
Первый пример работает, потому что вы бросаете синхронно, а не возвращаете будущее. Синхронный бросок перехватывается немедленно, а затем runZoned
возвращает null
. (Это, однако, должно измениться, когда Дарт получит ненулевые типы).
В общем, вероятно, плохая идея возвращать фьючерсы, которые могут содержать ошибки из runZoned
с помощью обработчика onError
. Мы не можем предотвратить это (возвращение Object
нормально, а фьючерсы являются объектами), но, возможно, это следует задокументировать.