如何通过Dart中的waitFor抛出未来

问题描述 投票:0回答:2

我是Dart dshell软件包的作者。

https://pub.dev/packages/dshell

Dshell是用于编写dart cli脚本的库和工具。

Dshell使用waitFor对用户隐藏期货,因为它们在典型的cli应用程序中几乎没有用。

我的问题是,如果future在由waitFor处理时抛出未处理的异常,则实际上会关闭应用程序。

我需要能够捕获任何异常,然后让调用者决定如何处理该异常。

这是到目前为止我尝试过的。没有任何catch技术将捕获未处理的异常:

import 'dart:async';

import 'dart:cli';

void main() {
  var future = throwException();
  try {
    future
        .catchError((Object e, StackTrace st) => print('onErrr: $e'))
        .whenComplete(() => print('future completed'));
    print(waitFor<int>(future));
  } // on AsyncError
  catch (e) {
    if (e.error is Exception) {
      print(e.error);
    } else if (e is AsyncError) {
      print('Rethrowing a non DShellException ${e}');
      rethrow;
    } else {
      print('Rethrowing a non DShellException ${e}');
      rethrow;
    }
  } finally {
    print('waitForEx finally');
  }
}

Future<int> throwException() {
  var complete = Completer<int>();

  Future.delayed(Duration(seconds: 2), () => throw Exception());
  return complete.future;
}


dart waitFor的一行使我认为这可能是不可能的:

如果Future正常完成,则返回其结果。如果Future以错误完成,则错误和堆栈跟踪将包装在AsyncError中并引发。如果在此调用期间运行的微任务或消息处理程序导致未处理的异常,则该异常将被传播,就好像微任务或消息处理程序是堆栈上唯一的Dart调用一样。也就是说,微任务或消息处理程序中未处理的异常将跳过对waitFor的调用中暂停的堆栈。

所以我对'以错误完成的未来'和'微任务...导致未处理的异常'之间的区别感到困惑。

exception dart command-line-interface future
2个回答
1
投票

Future返回的throwException永远不会以值或错误完成。 Future.delayed引发的错误是未处理的异步错误,它与从该方法返回的Future完全无关。获得带有错误的Future的方法是:

  • Future.error构造函数。
  • 在尚未完成的Completer.completeError上使用Completer
  • throw方法使用async
  • 在传递给throw构造函数或Future的回调中使用.then。>
  • 因此在您的示例中,Future.delayed创建了一个Future,由于回调中的throw,该错误将完成。没有人在听这个未来。没有await,没有链接的.then.catchError。一旦Future完成并出现错误,并且没有该错误的处理程序,它将冒泡到周围的错误区域。参见https://dart.dev/articles/archive/zones#handling-asynchronous-errors

如果您想对未处理的错误做出反应,可以使用runZoned-正确获取详细信息可能很棘手。请注意,运行一些代码可能会导致多个未处理的异步错误,并且Future的完成并不一定意味着以后不会出现其他未处理的异步错误。


0
投票

从内特·博世(Nate Bosch),我想出了一个可能的答案:

© www.soinside.com 2019 - 2024. All rights reserved.