处理异常 HTTP 请求颤动

Posted

技术标签:

【中文标题】处理异常 HTTP 请求颤动【英文标题】:Handling exception HTTP request flutter 【发布时间】:2020-06-24 04:50:26 【问题描述】:

我想处理带有一些错误消息的 http 请求抖动,但我在这里遇到了很多错误。我只是根据建议做的,但它对我不起作用。请任何人帮助我 这是我调用 API 的函数

getData(data, apiUrl) async 
    var tempUrl = _url + apiUrl + await _getToken();
    Uri uri = Uri.parse(tempUrl);
    var fullUrl = uri.replace(queryParameters: data);
    var res;
    try 
      var response = await http.get(fullUrl, headers: _setHeaders()).timeout(
          const Duration(seconds: 60));
      print(response.statusCode);
      if (response.statusCode != 200) 
        res = 
          "success": false,
          "status": response.statusCode,
          "message": _returnResponse(response)
        ;
      
      else 
        res = response;
      
    
    on SocketException 
      throw FetchDataException('No Internet connection');
    
    on TimeoutException catch (e) 
      res = 
        "success": false,
        "status": response.statusCode,
        "message": "Connection timeout"
      ;
     on Error catch (e) 
      print('Error: $e');
    

    return res;
  

这是我对除 200 以外的其他人的回复

dynamic _returnResponse(http.Response response) 
    switch (response.statusCode) 
      case 400:
        throw BadRequestException(response.body.toString());
      case 401:
      case 403:
        throw UnauthorisedException(response.body.toString());
      case 500:
      default:
        throw FetchDataException(
            'Error occured while Communication with Server with StatusCode : $response
                .statusCode');
    
  

这是我从 *** 和其他论坛获得的 app_exception.dart

class AppException implements Exception 
  final _message;
  final _prefix;

  AppException([this._message, this._prefix]);

  String toString() 
    return "$_prefix$_message";
  


class FetchDataException extends AppException 
  FetchDataException([String message])
      : super(message, "Error During Communication: ");


class BadRequestException extends AppException 
  BadRequestException([message]) : super(message, "Invalid Request: ");


class UnauthorisedException extends AppException 
  UnauthorisedException([message]) : super(message, "Unauthorised: ");


class InvalidInputException extends AppException 
  InvalidInputException([String message]) : super(message, "Invalid Input: ");

我尝试了很多建议,但根本没有用

我收到了这个错误

错误:“SocketException”不是一种类型。 在 SocketException ^^^^^^^^^^^^^^^

错误:“TimeoutException”不是一种类型。 在 TimeoutException 上捕获 (e) ^^^^^^^^^^^^^^^^

【问题讨论】:

【参考方案1】:

这里是一步一步的过程

首先添加http: ^0.13.4,然后按照以下步骤操作

1) 创建 API 基础助手类 为了在我们的远程服务器和应用程序之间进行通信,我们使用各种 API,这些 API 需要某种类型的 HTTP 方法来执行。所以我们首先要创建一个基础 API 帮助类,它将帮助我们与服务器进行通信。

import 'CustomException.dart';
import 'package:http/http.dart' as http;
import 'dart:io';
import 'dart:convert';
import 'dart:async';
import 'package:connectivity/connectivity.dart';

class APIManager 

  Future<dynamic> postAPICall(String url, Map param) async 
    print("Calling API: $url");
    print("Calling parameters: $param");

    var responseJson;
    try 
      final response =  await http.post(url,
      body: param);
      responseJson = _response(response);
     on SocketException 
      throw FetchDataException('No Internet connection');
    
    return responseJson;
  

  dynamic _response(http.Response response) 
    switch (response.statusCode) 
      case 200:
        var responseJson = json.decode(response.body.toString());
        return responseJson;
      case 400:
        throw BadRequestException(response.body.toString());
      case 401:
      case 403:
        throw UnauthorisedException(response.body.toString());
      case 500:
      default:
        throw FetchDataException(
          'Error occured while Communication with Server with StatusCode: $response.statusCode');
    
  

2) 创建自定义异常类

执行时的 HTTP 请求可以根据其状态返回各种类型的状态代码。如果请求失败,我们不希望我们的应用程序行为异常,因此我们将在我们的应用程序中处理其中的大部分。为此,我们将创建我们可以根据响应状态代码抛出的自定义应用程序异常。

class CustomException implements Exception 
  final _message;
  final _prefix;

  CustomException([this._message, this._prefix]);

  String toString() 
  return "$_prefix$_message";
  


class FetchDataException extends CustomException 
  FetchDataException([String message])
  : super(message, "Error During Communication: ");


class BadRequestException extends CustomException 
  BadRequestException([message]) : super(message, "Invalid Request: ");


class UnauthorisedException extends CustomException 
  UnauthorisedException([message]) : super(message, "Unauthorised: ");


class InvalidInputException extends CustomException 
  InvalidInputException([String message]) : super(message, "Invalid Input: ");

3) 创建一个从 API 获取数据的方法

调用 API:- 用于从 API 获取数据

void signIn(Map param)  
  setState(() 
    _isLoading = true;
  );
  apiManager.postAPICall(BASE_URL + user_login, param).then((value) 
    var status_code = value["statuscode"];
    if (status_code == 200) 
      var userData = value["user_data"];
      Navigator.push(context, PageTransition(type: 
      PageTransitionType.rightToLeftWithFade, child: HouseholderHomeScreen()));

      setState(() 
        _isLoading = false;
      );
     else 
      setState(() 
        _isLoading = false;
      );
      _scaffoldKey.currentState.showSnackBar(
          SnackBar(
            content: new Text(value["msg"]),
            backgroundColor: Colors.red,
            duration: new Duration(seconds: 2),
          )
      );
    
 , onError: (error) 
    setState(() 
      _isLoading = false;
    );
    print("Error == $error");
    _scaffoldKey.currentState.showSnackBar(
      SnackBar(
        content: new Text('Something went wrong..'),
        duration: new Duration(seconds: 2),
      )
    );
    print(error);
  );

【讨论】:

第一步,你应该在调用API之前解析你的url,await http.post(Uri.parse(url), body: param);【参考方案2】:

我使用了 dio 包。这比我做的更容易,错误更少

https://pub.dev/packages/dio

【讨论】:

很有前途的库,但对我来说效果不佳。在调用已经被 try/catch 块包围的情况下抛出未处理的异常。而且这个问题已经在问题跟踪器上打开了几个月,没有任何回应【参考方案3】:

如果发生的错误发生在 SocketException 和 Timeout 异常上,请确保您已分别在该文件中导入了 dart.iodart.async。根据您的代码,我能够成功运行它,但您可以参考 Paresh Mangukiya 的answer 一步一步地了解或参考here 以进一步说明如何使用自定义错误响应处理网络调用和异常颤抖。

【讨论】:

以上是关于处理异常 HTTP 请求颤动的主要内容,如果未能解决你的问题,请参考以下文章

发布 http 请求:在 null 颤动上调用了 getter 'length'

颤动如何在http.get请求中传递变量

在颤动中打印休息请求错误时出现问题

没有为请求类型“GET”找到 HTTP 处理程序

HTTP状态码分类及异常状态码处理

无法在运行发布颤动时发布 https 请求