flutter - Dart - 无法捕获异步异常

标签 flutter dart async-await try-catch timeoutexception

这是我的问题的一个简单示例:

import 'dart:async';

void main() {
  try {
    Timer(Duration(seconds: 1), () {
      throw TimeoutException('1 second has expired');
    });
  } catch (o) {
    print("caught ${o.runtimeType}");
  }
}

我想问题是计时器在 try-catch block 终止后完成倒计时,考虑到倒计时是异步的并初始化 Timer那是成功的。如何在不改变Timer的回调函数的情况下捕获异常?

在我的具体情况下,我使用 flutter_blue并在使用异步方法时遇到问题 BluetoothDevice#connect() .

/// Establishes a connection to the Bluetooth Device.
Future<void> connect({
  Duration? timeout,
  bool autoConnect = true,
}) async {
  var request = protos.ConnectRequest.create()
    ..remoteId = id.toString()
    ..androidAutoConnect = autoConnect;

  Timer? timer;
  if (timeout != null) {
    timer = Timer(timeout, () {
      disconnect();
      throw TimeoutException('Failed to connect in time.', timeout);
    });
  }

  await FlutterBlue.instance._channel
      .invokeMethod('connect', request.writeToBuffer());

  await state.firstWhere((s) => s == BluetoothDeviceState.connected);

  timer?.cancel();

  return;
}

我这样调用该方法:

try {
  await (device as BluetoothDevice).connect(timeout: Duration(seconds: 1));
} catch (o) {
  print("caught ${o.runtimeType}");
}

考虑到我等待BluetoothDevice#connect()await成功连接后(在方法结束时)定时器将被取消 timer?.cancel(); ,我不知道为什么 try-catch 没有捕获以下 TimeoutException :

E/flutter ( 3710): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: TimeoutException after 0:00:01.000000: Failed to connect in time.
E/flutter ( 3710): #0      BluetoothDevice.connect.<anonymous closure> (package:flutter_blue/src/bluetooth_device.dart:33:9)
E/flutter ( 3710): #1      _rootRun (dart:async/zone.dart:1346:47)
E/flutter ( 3710): #2      _CustomZone.run (dart:async/zone.dart:1258:19)
E/flutter ( 3710): #3      _CustomZone.runGuarded (dart:async/zone.dart:1162:7)
E/flutter ( 3710): #4      _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1202:23)
E/flutter ( 3710): #5      _rootRun (dart:async/zone.dart:1354:13)
E/flutter ( 3710): #6      _CustomZone.run (dart:async/zone.dart:1258:19)
E/flutter ( 3710): #7      _CustomZone.bindCallback.<anonymous closure> (dart:async/zone.dart:1186:23)
E/flutter ( 3710): #8      Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:18:15)
E/flutter ( 3710): #9      _Timer._runTimers (dart:isolate-patch/timer_impl.dart:395:19)
E/flutter ( 3710): #10     _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:426:5)
E/flutter ( 3710): #11     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)
E/flutter ( 3710): 

我看到堆栈跟踪从 BluetoothDevice#connect() 开始,但我不知道该怎么办。

我也尝试调用then((_) {}, (o) => print("caught ${o.runtimeType}"))关于Future<void>返回者 BluetoothDevice#connect()然后在try-catch中等待它,但我没有成功。

有什么想法吗?

最佳答案

您正在使用的包中的 connect 方法写得不好。你没有做错任何事,无论是谁写的代码都做错了。如果您浏览该存储库的 GitHub Issues 部分,您会发现很多问题以及与此问题相关的拉取请求,例如 this以及它链接的问题/公关。

计时器回调中的代码存在于实例化计时器的函数之外。不可能直接捕获计时器回调中抛出的错误。

如果你想要超时,不要使用这个包提供的功能,使用原生Dart timeout功能。

try {
  await (device as BluetoothDevice).connect().timeout(Duration(seconds: 1));
} catch (o) {
  print("caught ${o.runtimeType}");
}

关于flutter - Dart - 无法捕获异步异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68658256/

相关文章:

flutter - Android Studio - 'constants.dart' 文件变成 .txt 文件

swift - 传入runtimeType作为通用函数参数

c# - 如何让 ActionBlock 在发生任何异常时运行

c# - 我应该如何将返回非泛型任务的函数转换为 ValueTask?

c# - 异步一次性创建

dart - Flutter:无法从 Firebase 身份验证中获取错误代码?

flutter - 通过点击缩略图加载全屏图像

xcode - 如何强制 Flutter 更新我的版本和内部版本号?

asynchronous - 在 Dart 中,如何确保流更新在继续之前完成?

flutter - 如何使中间容器与其他两个容器不同?