此方法提交一个简单的HTTP请求并调用成功或错误回调:
void _getSimpleReply( String command, callback, errorCallback ) async {
try {
HttpClientRequest request = await _myClient.get( _serverIPAddress, _serverPort, '/' );
HttpClientResponse response = await request.close();
response.transform( utf8.decoder ).listen( (onData) { callback( onData ); } );
} on SocketException catch( e ) {
errorCallback( e.toString() );
}
}
如果服务器未运行,则Android应用或多或少会立即调用errorCallback。
在iOS上,errorCallback会花费很长的时间-超过20秒-直到调用任何回调。
我可以为HttpClient()设置等待服务器端返回回复的最大秒数-如果有的话?
答案 0 :(得分:24)
您可以使用timeout
http.get('url').timeout(
Duration(seconds: 1),
onTimeout: () {
// time has run out, do what you wanted to do
return null;
},
);
答案 1 :(得分:8)
有两种方法可以在Dart中配置此行为
您可以使用Future.timeout
方法在任何Future上设置超时。在给定的持续时间过去之后,这会通过抛出TimeoutException
来短路。
try {
final request = await client.get(...);
final response = await request.close()
.timeout(const Duration(seconds: 2));
// rest of the code
...
} on TimeoutException catch (_) {
// A timeout occurred.
} on SocketException catch (_) {
// Other exception
}
您还可以使用HttpClient.connectionTimeout
在HttpClient本身上设置超时。设置超时后,这将适用于同一客户端发出的所有请求。当请求超过此超时时间时,将引发SocketException
。
final client = new HttpClient();
client.connectionTimeout = const Duration(seconds: 5);
答案 2 :(得分:3)
HttpClient.connectionTimeout 对我不起作用。但是,我知道 Dio 数据包允许取消请求。然后,我深入研究数据包以了解他们是如何实现它的,并根据我的需要进行了调整。我所做的是创建两个未来:
Future.delayed
,我可以在其中设置超时的持续时间。然后,我将两个期货传递给 Future.any
,它返回要完成的第一个期货的结果,并丢弃所有其他期货的结果。因此,如果超时未来先完成,您的连接将超时并且不会收到任何响应。您可以在以下代码中查看:
Future<Response> get(
String url, {
Duration timeout = Duration(seconds: 30),
}) async {
final request = Request('GET', Uri.parse(url))..followRedirects = false;
headers.forEach((key, value) {
request.headers[key] = value;
});
final Completer _completer = Completer();
/// Fake timeout by forcing the request future to complete if the duration
/// ends before the response arrives.
Future.delayed(timeout, () => _completer.complete());
final response = await Response.fromStream(await listenCancelForAsyncTask(
_completer,
Future(() {
return _getClient().send(request);
}),
));
}
Future<T> listenCancelForAsyncTask<T>(
Completer completer,
Future<T> future,
) {
/// Returns the first future of the futures list to complete. Therefore,
/// if the first future is the timeout, the http response will not arrive
/// and it is possible to handle the timeout.
return Future.any([
if (completer != null) completeFuture(completer),
future,
]);
}
Future<T> completeFuture<T>(Completer completer) async {
await completer.future;
throw TimeoutException('TimeoutError');
}
答案 3 :(得分:1)
没有使用Dart的http
设置超时的选项。但是,当它返回Future
时,我们可以在Future
上设置超时。
下面的示例将超时设置为15秒。如果已经15秒并且没有收到响应,它将抛出TimeoutException
Future<dynamic> postAPICall(String url, Map param, BuildContext context) async {
try {
final response = await http.post(url,
body: param).timeout(const Duration(seconds: 10),onTimeout : () {
throw TimeoutException('The connection has timed out, Please try again!');
});
print("Success");
return response;
} on SocketException {
print("You are not connected to internet");
}
}