future 中 try-catch 和 catchError,你用对了吗

2,392 阅读1分钟

前言

我们知道dart是一种单线程语言,我们执行异步操作借助的是它的 event loop 机制,Future是我们最常用到的一个工具,常见用法如下:

  Future testFuture() {
    ... 此处进行耗时操作
  }
  //调用处
  main() async {
  //第一种,同步会阻塞
  await testFuture();
  //第二种,异步非阻塞
  testFuture().then((value) {});
  }

捕获异常的方式

对于同步的future,我们使用try-catch进行异常捕获

try {
  await testFuture();
} catch(e){
  print(e.toString());
}

对于异步的future,有两种方式进行异常捕获

testFuture().then((value){
      //成功回调
      },onError: (_) {
      //方式1,使用onError
      }).catchError((e) {
      //方式2,使用catchError
      }););

方式1:使用 onError(onError优先级大于catchError,因此当 catchError 和 onError 同时存在时,会命中 onError 方法)

方式2:使用 catchError

分享一个catchError失败的案例:

Future testFuture() {
   throw AssertionError("assert error2");
}
//调用处
main() {
try {
      testFuture().then((value) {}, onError(_){
      print("onError error");
      })
    } catch (e) {
      print("try-catch error");
    }
}

运行发现,onError 并没有被命中,而是被 try-catch 捕获了异常。我们又尝试在 testFuture 方法后加上 asyhc 进行修饰,声明告知这是一个异步结果,此时 onError 会被命中。 或者,我们将 throw AssertionError("assert error2") 改为 return Future.error("assert error2") , onError 也会被命中。

结论: 只有在异步队列中发生的异常才会被 onError 命中,其他情况视为同步代码,直接被 try-catch 捕获。