无法捕获异步异常
Cannot catch an asynchronous exception
这是我的问题的一个简单示例:
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 并且在使用异步方法 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}");
}
考虑到我用 await
等待 BluetoothDevice#connect()
并且在用 timer?.cancel();
成功连接(在方法结束时)后计时器被取消,我不知道为什么要尝试-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()
开始,但我不确定该怎么做。
我也尝试在 BluetoothDevice#connect()
返回的 Future<void>
上调用 then((_) {}, (o) => print("caught ${o.runtimeType}"))
然后在 try-catch 中等待它,但我没有成功。
有什么想法吗?
您使用的包中的 connect
方法写得不好。你没有做错任何事,不管是谁写的代码。如果您浏览该存储库的 GitHub 问题部分,您会发现很多问题和与此问题相关的拉取请求,例如 this 和它链接的 issues/PR。
计时器回调中的代码存在于实例化计时器的函数之外。无法直接捕获计时器回调中抛出的错误。
如果你想要超时,不要使用这个包提供的功能,使用原生的 Dart timeout
函数。
try {
await (device as BluetoothDevice).connect().timeout(Duration(seconds: 1));
} catch (o) {
print("caught ${o.runtimeType}");
}
这是我的问题的一个简单示例:
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 并且在使用异步方法 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}");
}
考虑到我用 await
等待 BluetoothDevice#connect()
并且在用 timer?.cancel();
成功连接(在方法结束时)后计时器被取消,我不知道为什么要尝试-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()
开始,但我不确定该怎么做。
我也尝试在 BluetoothDevice#connect()
返回的 Future<void>
上调用 then((_) {}, (o) => print("caught ${o.runtimeType}"))
然后在 try-catch 中等待它,但我没有成功。
有什么想法吗?
您使用的包中的 connect
方法写得不好。你没有做错任何事,不管是谁写的代码。如果您浏览该存储库的 GitHub 问题部分,您会发现很多问题和与此问题相关的拉取请求,例如 this 和它链接的 issues/PR。
计时器回调中的代码存在于实例化计时器的函数之外。无法直接捕获计时器回调中抛出的错误。
如果你想要超时,不要使用这个包提供的功能,使用原生的 Dart timeout
函数。
try {
await (device as BluetoothDevice).connect().timeout(Duration(seconds: 1));
} catch (o) {
print("caught ${o.runtimeType}");
}