flutter - 无法捕获异步异常
问题描述
这是我的问题的一个简单示例:
import 'dart:async';
void main() {
try {
Timer(Duration(seconds: 1), () {
throw TimeoutException('1 second has expired');
});
} catch (o) {
print("caught ${o.runtimeType}");
}
}
我想问题是定时器在 try-catch 块终止后完成倒计时,考虑到倒计时是异步的并且初始化Timer
成功。如何在不更改回调函数的情况下捕获异常Timer
?
在我的具体情况下,我正在使用flutter_blue并且在使用 async 方法时遇到了问题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()
withawait
并且计时器在与 with 成功连接(在方法结束时)时被取消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()
,但我不知道该怎么做。
我也尝试调用返回的 bythen((_) {}, (o) => print("caught ${o.runtimeType}"))
然后在 try-catch 中等待它,但我没有成功。Future<void>
BluetoothDevice#connect()
有任何想法吗?
解决方案
That connect
method from the package you're using is poorly written. You're not doing anything wrong, whoever wrote that code did. If you poke around the GitHub Issues sections of that repository you'll find quite a few issues and pull requests related to this problem like this and the issues/PR it links.
The code in a timer callback exists outside of the function where the timer is instantiated. It's impossible to directly catch an error thrown in a timer callback.
If you want a timeout, don't use the functionality provided by this package, use the native Dart timeout
function.
try {
await (device as BluetoothDevice).connect().timeout(Duration(seconds: 1));
} catch (o) {
print("caught ${o.runtimeType}");
}
推荐阅读
- apache-kafka - Kafka Connect 接收器任务忽略容差限制
- jquery - Worpdress 上的 Google Analytics 事件跟踪
- angular - 在 angular7 中实现引导模式对话框
- angular - 从本地 Angular 库自动导入包括“public-api”并中断应用程序
- javascript - 如何将 react-boostrap 与 next.js 和 React.js 一起使用
- amazon-web-services - 如何设置我的 API 以要求使用 amazon API Gateway 的 API 密钥?
- hibernate - JSON没有被Jackson隐式转换为RequestBody对象依赖于Spring Mvc中的发布请求?
- sql - 将主表的数据与键值属性连接形成另一个以键为列的表
- python - Matplotlib 次要刻度禁用
- security - S/MIME 和 HTTPS 之间的 X.509 证书差异 (LetsEncrypt)