设置HTTPClient get()请求的超时时间

Ste*_*eAp 12 dart flutter

此方法提交一个简单的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() );

    }
  }
Run Code Online (Sandbox Code Playgroud)

如果服务器没有运行,Android-app或多或少会立即调用errorCallback.

在iOS上,errorCallback需要很长一段时间 - 超过20秒 - 直到调用任何回调.

我可以为HttpClient()设置一个等待服务器端返回回复的最大秒数 - 如果有的话?

Cop*_*oad 43

您可以使用 timeout

http.get(Uri.parse('url')).timeout(
  Duration(seconds: 1),
  onTimeout: () {
    // Time has run out, do what you wanted to do.
    return http.Response('Error', 500); // Replace 500 with your http code.
  },
);
Run Code Online (Sandbox Code Playgroud)

  • 这个答案可能应该澄清它使用的是 `package:http` 而不是 `dart:io` 的 `HttpClient`。 (4认同)

Jon*_*ams 30

在Dart中有两种不同的方法来配置此行为

设置每个请求超时

您可以使用该Future.timeout方法在任何Future上设置超时.这将在给定的持续时间过去之后通过投掷a来短路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
}
Run Code Online (Sandbox Code Playgroud)

在HttpClient上设置超时

您还可以使用HttpClient本身设置超时HttpClient.connectionTimeout.这将适用于设置超时后由同一客户端发出的所有请求.当请求超过此超时时,SocketException抛出a.

final client = new HttpClient();
client.connectionTimeout = const Duration(seconds: 5);
Run Code Online (Sandbox Code Playgroud)

  • 对于任何未来的读者,请参阅@ch271828n的问题:[Proper way of set request timeout for Flutter http requests?](/sf/ask/4803076211/)。 (5认同)
  • 连接超时和请求超时是两个不同的概念。此答案中指定的这两种方式不可互换,并且每种方式都执行不同的操作。 (2认同)

小智 5

HttpClient.connectionTimeout对不起作用。不过,我知道Dio数据包允许取消请求。然后,我深入研究数据包,了解他们是如何实现这一目标的,并根据我的情况进行了调整。我所做的是创造两个未来:

  • 我在其中Future.delayed设置超时持续时间。
  • HTTP 请求。

然后,我将两个 future 传递给 a Future.any,它返回第一个 future 完成的结果,并丢弃所有其他 future 的结果。因此,如果超时 future 首先完成,您的连接将超时并且不会收到任何响应。您可以通过以下代码查看:

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');
  }
Run Code Online (Sandbox Code Playgroud)