Почему отправка следующего запроса заканчивается неперехваченным исключением?

#flutter #dart

Вопрос:

У меня есть следующая функция кода Flutter amp; Dart, которая отправляет запрос на сервер:

 Future<void> autoAuth(BuildContext ctx) async {
  final url = Uri.parse('${this._baseURL.toString()}/auto-auth');

  try {
    final deviceStorage = await SharedPreferences.getInstance();

    if (deviceStorage.getString('refreshToken') == null) {
      return this._setUser(null);
    }

    final response = await http.post(url, headers: {
      'Authorization': 'Bearer ${deviceStorage.getString('refreshToken')!}',
    }).timeout(const Duration(seconds: 3));
    final Map<String, dynamic> responseBody = json.decode(response.body);

    if (responseBody['success']) {
      this._refreshAccessToken(ctx, deviceStorage);

      return this._setUser(new User(
        id: responseBody['data']['id'],
        isSubscribed: responseBody['data']['isSubscribed'],
        playlistId: responseBody['data']['playlistId'],
      ));
    }

    this._setUser(null);
  } on SocketException {
    this._setUser(null);

    throw Error();
  } on TimeoutException {
    this._setUser(null);

    throw Error();
  } catch (_) {
    this._setUser(null);
  }
}
 

Обратите внимание, что URL-адрес намеренно неверен, поэтому время ожидания запроса истекает.
Но для этого я закодировал: .timeout(...) по будущему запросу. Таким образом, в принципе, через 3 секунды он должен быть пойман с помощью on TimeoutException исключения.

Это так и происходит. Однако примерно через 1 минуту (вероятно, какой-то тайм-аут http-запроса по умолчанию в dart) я получаю необнаруженное исключение, потому что время ожидания запроса истекло. Где я ошибаюсь?

Комментарии:

1. Вы не можете отменить a Future . Использование .timeout() заставит a TimeoutException быть выброшенным, если указанное Future не завершится в течение отведенного времени, но это не помешает исходному Future завершению в конечном итоге (успешно или с ошибкой).

2. @jamesdlin В этом есть смысл. Итак, как я могу поймать эту ошибку?

Ответ №1:

Это потому, что вы используете его неправильно. .timeout Код, который вы используете, — это общий тайм-аут на любое будущее. Таким образом, вы улавливаете ошибку будущего тайм-аута, но не улавливаете ошибку, возникающую из тайм-аута http-запроса.

Чтобы использовать его правильно, сначала добавьте следующий импорт: import 'package:http/io_client.dart' as http;

Затем измените код на:

 final ioClient = HttpClient();
ioClient.connectionTimeout = const Duration(seconds: 3);
final client = http.IOClient(ioClient);

final response = await client.post(url, headers: {
  'Authorization': 'Bearer ${deviceStorage.getString('refreshToken')!}',
});