我正在尝试将onTimeout回调设置为HttpClientRequest未来的timeout 方法。
下面的示例编译时没有错误。但是,当运行时,它会引发以下未处理的异常:
type '() => Future<HttpClientRequest>' is not a subtype of type '(() => FutureOr<_HttpClientRequest>)?' of 'onTimeout'。
我对飞镖/颤振很陌生,很难理解回调方法失败的原因。
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;
}发布于 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>是T和Future<T>类型的特殊联合,因此返回Future<HttpCientRequest>的函数是返回FutureOr<HttpClientRequest>的函数的子类型(即兼容)。然而,人们期望的是一个FutureOr<_HttpClientRequest>。_HttpClientRequest?这是从哪里来的,为什么不兼容呢?
即使不知道实现细节,我们也可以假定_HttpClientRequest是HttpClientRequest的某些子类型。错误消息意味着,当我们调用HttpClient.get时,返回对象的静态(在编译时已知)类型是Future<HttpClientRequest>,但实际运行时类型是Future<_HttpClientRequest>。如果类型Derived是Base的子类型,那么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,因此最终会出现运行时错误。
你怎么能解决这个问题?
一些备选方案:
HttpClient.get返回运行时类型为Future<_HttpClientRequest>而不是Future<HttpClientRequest>的对象。_HttpClientRequest是一个私有类型,所以实际上不能自己返回该类型的对象。但是,您可以使用Future.value从Future<_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回调返回的值。我不知道这是否是您想要的,不过在这种情况下,如果您只想记录一个请求花了太长时间的话,可能没问题。
发布于 2022-06-10 16:00:39
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;
}
}然后在主函数中
final response = await requestify();
if (response != null) {
// HttpClientRequest
} else {
// timeout
}https://stackoverflow.com/questions/72576065
复制相似问题