为什么我不能捕获这个 TimeoutException

Why can't i catch this TimeoutException

我目前正在为 Web 构建一个 Stomp WebSocket 连接,我想在其中控制连接超时值。这是我的连接方法:

Future<WebSocketChannel> connect(StompConfig config) {
  final completer = Completer<HtmlWebSocketChannel>();
  final webSocket = WebSocket(config.url)..binaryType = BinaryType.list.value;
  var onOpenEvent = webSocket.onOpen.first;
  if (config.connectionTimeout.inMilliseconds > 0) {
    onOpenEvent = onOpenEvent.timeout(config.connectionTimeout);
  }
  onOpenEvent.then((value) {
    completer.complete(HtmlWebSocketChannel(webSocket));
  });
  webSocket.onError.first.then((err) {
    completer.completeError(WebSocketChannelException.from(err));
  });

  return completer.future;
}

我是这样称呼它的:

try {
    _channel = await platform.connect(config);
} catch (err) {
   print('Caught error');
}

遗憾的是我似乎无法捕捉到 onOpenEvent.timeout(..) 抛出的 TimeoutException。相反,它只是打印这个(看似未捕获的异常):

Error: TimeoutException after 0:00:05.000000: Future not completed
    at Object.createErrorWithStack (http://localhost:59275/dart_sdk.js:5044:12)
    at Object._rethrow (http://localhost:59275/dart_sdk.js:37476:16)
    at async._AsyncCallbackEntry.new.callback (http://localhost:59275/dart_sdk.js:37472:13)
    at Object._microtaskLoop (http://localhost:59275/dart_sdk.js:37332:13)
    at _startMicrotaskLoop (http://localhost:59275/dart_sdk.js:37338:13)
    at http://localhost:59275/dart_sdk.js:33109:9

我做错了什么?我以前的代码看起来像这样并且适用于 TimeoutException,但遗憾的是不适用于 WebSocket 抛出的任何其他异常:

Future<WebSocketChannel> connect(StompConfig config) async {
  final webSocket = WebSocket(config.url)..binaryType = BinaryType.list.value;
  var onOpenEvent = webSocket.onOpen.first;
  if (config.connectionTimeout.inMilliseconds > 0) {
    onOpenEvent = onOpenEvent.timeout(config.connectionTimeout);
  }
  await onOpenEvent;
  return HtmlWebSocketChannel(webSocket);
}

感谢任何建议!

可以捕获异常,只是您没有。 语句

  onOpenEvent.then((value) {
    completer.complete(HtmlWebSocketChannel(webSocket));
  });

监听 onOpenEvent 未来,并创建一个新的 Future 作为结果。 当 onOpenEvent 完成并出现超时异常时,此 then 调用会收到错误,并且由于它没有 处理 异常,因此它返回的未来也会完成同样的例外。

自从上面的语句丢弃它以来,没有人接触过那个 future,因此那个 future 的结果是一个未处理的错误

您之前的代码起作用的原因是 await onOpenEvent(重新)抛出 该错误并使其成为整个 connect 调用的结果。

新代码无法让该错误到达 connect 函数调用,onOpenEvent.then(...) 未来可能会在 connect 返回后完成。

您可以尝试向 then 调用添加错误处理程序:

  onOpenEvent.then((value) {
    completer.complete(HtmlWebSocketChannel(webSocket));
  }, onError: (error, StackTrace stackTrace) {
    if (!completer.isCompleted) completer.completeError(error, stackTrace);
  });
  webSocket.onError.first.then((err) {
    if (!completer.isCompleted) {    
      completer.completeError(WebSocketChannelException.from(err));
    }
  });