首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >设置HttpClientRequest未来的超时回调会引发未处理的异常

设置HttpClientRequest未来的超时回调会引发未处理的异常
EN

Stack Overflow用户
提问于 2022-06-10 14:39:19
回答 2查看 180关注 0票数 1

我正在尝试将onTimeout回调设置为HttpClientRequest未来的timeout 方法

下面的示例编译时没有错误。但是,当运行时,它会引发以下未处理的异常:

type '() => Future<HttpClientRequest>' is not a subtype of type '(() => FutureOr<_HttpClientRequest>)?' of 'onTimeout'

我对飞镖/颤振很陌生,很难理解回调方法失败的原因。

代码语言:javascript
复制
void main() async {
  requestify();
}

Future<HttpClientRequest> requestify() async {
  var client = HttpClient();
  var request = client.get('10.255.255.1', 80, '');
  // request.timeout(const Duration(seconds: 1));
  request.timeout(const Duration(seconds: 1), onTimeout: () {
    print('timed out');
    return request;
  });
  return request;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-06-10 20:13:09

让我们更仔细地研究类型错误:

type '() => Future<HttpClientRequest>' is not a subtype of type '(() => FutureOr<_HttpClientRequest>)?' of 'onTimeout'.

提供一个返回Future<HttpClientRequest>的回调函数。

所期望的是一个返回FutureOr<_HttpClientRequest>的函数。

FutureOr<T>TFuture<T>类型的特殊联合,因此返回Future<HttpCientRequest>的函数是返回FutureOr<HttpClientRequest>的函数的子类型(即兼容)。然而,人们期望的是一个FutureOr<_HttpClientRequest>_HttpClientRequest?这是从哪里来的,为什么不兼容呢?

即使不知道实现细节,我们也可以假定_HttpClientRequestHttpClientRequest的某些子类型。错误消息意味着,当我们调用HttpClient.get时,返回对象的静态(在编译时已知)类型是Future<HttpClientRequest>,但实际运行时类型是Future<_HttpClientRequest>。如果类型DerivedBase的子类型,那么Dart还将GenericClass<Derived>视为GenericClass<Base>的子类型。通常情况下,这是可以的,并且返回一个函数声明返回的更窄的子类型是安全的。

当您尝试对返回的.timeout调用Future<_HttpClientRequest>时,就会出现问题。Future<T>.timeout的回调必须返回一个FutureOr<T>。但是,您正在对运行时类型为Future<_HttpClientRequest>的对象调用.timeout,因此您的回调也必须返回_HttpClientRequest。返回基类类型(HttpClientRequest)无效,因为不能返回更窄类型的更宽类型。

(另一种情况是,将Dart给出未处理的异常: type不是“value”类型的子类型。视为GenericClass<Base>的一个子类型可能会导致令人惊讶的运行时错误,请参见GenericClass<Derived>。)

TL;DR

据分析器和编译器所知,您正在使用返回HttpClientRequest的回调在Future<HttpClientRequest>上调用HttpClientRequest,因此没有编译时错误。但是,在运行时,您实际上是使用返回一个.timeout的回调函数在Future<_HttpClientRequest>上调用HttpClientRequest,因此最终会出现运行时错误。

你怎么能解决这个问题?

一些备选方案:

  • 考虑对Dart SDK问题进行归档,以HttpClient.get返回运行时类型为Future<_HttpClientRequest>而不是Future<HttpClientRequest>的对象。
  • 因为_HttpClientRequest是一个私有类型,所以实际上不能自己返回该类型的对象。但是,您可以使用Future.valueFuture<_HttpClientRequest>:// client.get中构造一个新的client.get,它可能会返回一个完成// HttpClientRequest子类型的Future。变量请求= Future.value(client.get('10.255.255.1',80,‘’);request.timeout(持续时间(秒: 1),onTimeout:() { print('timed‘);返回请求;});返回请求;
  • 避免使用回调类型的奇怪之处,方法是不将Future.timeout与回调一起使用,而是捕获结果的TimeoutException

我还将指出,Future.timeout返回一个新的Future,但是您将返回原始的Future,并且不会使用timeout回调返回的值。我不知道这是否是您想要的,不过在这种情况下,如果您只想记录一个请求花了太长时间的话,可能没问题。

票数 1
EN

Stack Overflow用户

发布于 2022-06-10 16:00:39

代码语言:javascript
复制
Future<HttpClientRequest?> requestify() async {
  try {
    var client = HttpClient();
    var request = await client.get("10.255.255.1", 80, "")
                       .timeout(const Duration(seconds: 1));
    return request;
  } on TimeoutException catch(e) {
    return null;
  }
}

然后在主函数中

代码语言:javascript
复制
final response = await requestify();
if (response != null) {
   // HttpClientRequest
} else {
   // timeout
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72576065

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档