【问题标题】:Why doesn't my method work in DioError catch in Flutter/Dart?为什么我的方法在 Flutter/Dart 中的 DioError catch 中不起作用?
【发布时间】:2022-08-23 06:21:18
【问题描述】:

我正在向我的数据库发出这样的请求:

//Airtable (find a record)
  void airtableFind() async {
    try {
      final response = await Dio().get(
        \'https://api.airtable.com/v0/\'+projectBase+\'/\'+recordName,
        queryParameters: {
          \'filterByFormula\': \'SEARCH(\'+\'\"\'+username+\'\"\'+\',{Name})\' // Searches the value \'Cactus\' in the {\'Short description\'} field.
        },
        options: Options(
          contentType: \'Application/json\',
          headers: {
            \'Authorization\': \'Bearer\'+\' \'+apiKey,
            \'Accept\': \'Application/json\',
          },
        ),
      );

      // TODO: Whatever you want to do with the response. A good practice is to transform it into models and than work with them
      // print(response);
      // print(response.data[\'records\'][0][\'id\']);
      idString = response.data[\'records\'][0][\'id\'];
      // if (idString.isNotEmpty) (
      //     showInvalidUsernameDialog(context)
      //     // TODO: Need to inform about success
      // );

    } on DioError catch (e) {
      // TODO: Error handling
      if (e.response != null) {
        // print(e.response.data);
        print(e);
        showInvalidUsernameDialog(context);

      } else {
        // print(e.request);
        print(e.message);
        showInvalidUsernameDialog(context);
      }
    }
  }

如果我的用户输入了正确的单词(用户名),那么一切正常。但总是有一个人犯错的风险。我想用showInvalidUsernameDialog(context); 对话框来表明这一点,但由于某种原因它没有弹出。

我在控制台中看到错误:

I/flutter(4484): DioError [DioErrorType.response]: Http status error [422]
I/flutter ( 4484): Source stack:
I/flutter(4484): #0 DioMixin.fetch(package:dio/src/dio_mixin.dart:488:35)
I/flutter ( 4484): #1 DioMixin.request (package:dio/src/dio_mixin.dart:483:12)
I/flutter ( 4484): #2 DioMixin.patch (package:dio/src/dio_mixin.dart:249:12)
I/flutter(4484): #3 _RouteState.airtableUpdate(package:example/main.dart:1498:36)
I/flutter ( 4484): #4 _RouteState.build.<anonymous closure> (package:example/main.dart:1617:13)
I/flutter ( 4484): #5 _RouteState.build.<anonymous closure> (package:example/main.dart:1612:24)
I/flutter(4484): #6 EditableTextState._finalizeEditing (package:flutter/src/widgets/editable_text.dart:2148:18)
I/flutter(4484): #7 EditableTextState.performAction(package:flutter/src/widgets/editable_text.dart:1999:9)
I/flutter(4484): #8 TextInput._handleTextInputInvocation(package:flutter/src/services/text_input.dart:1746:37)
I/flutter ( 4484): #9 MethodChannel._handleAsMethodCall (package:flutter/src/services/platform_channel.dart:404:55)
I/flutter ( 4484): #10 MethodChannel.setMethodCallHandler.<anonymous closure> (package:flutter/src/services/platform_chan
E/flutter ( 4484): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: RangeError (index): Invalid value: Valid value range is empty: 0
E/flutter ( 4484): #0 List.[] (dart:core-patch/growable_array.dart:264:36)
E/flutter ( 4484): #1 _RouteState.airtableFind (package:example/main.dart:1473:42)
E/flutter ( 4484): <asynchronous suspension>
E/flutter ( 4484):

这是意料之中的,因为我故意输入了错误的用户名。但我不仅想获得控制台中的错误列表,还想获得一个对话框。为什么不出现?

对话框调用方法正确。我把它放在用户名有效时触发的代码部分。它看起来完全符合预期。

但是为什么这个方法在这部分代码中不起作用呢?

on DioError catch (e) {
      // TODO: Error handling
      if (e.response != null) {
        // print(e.response.data);
        print(e);
        showInvalidUsernameDialog(context);

      } else {
        // print(e.request);
        print(e.message);
        showInvalidUsernameDialog(context);
      }

如果出现错误,我怎样才能让这个对话框出现?

编辑 1. _RouteState.airtableFind (package:example/main.dart:1473:42) 指的是idString = response.data[\'records\'][0][\'id\'];。当我的用户错误地输入他们的登录名时,就会发生这种情况。

  • _RouteState.airtableFind (package:example/main.dart:1473:42) 指的是哪一行?你能提供一个最小的、可重现的例子吗?
  • 我添加了Edit 1,如果这足够了。
  • 来自控制台的堆栈跟踪可能是一条红鲱鱼。 DioError.toString 可能包含堆栈跟踪,因此实际上可能没有未捕获的异常。如果showInvalidUsernameDialog 不能在catch 块内工作,则showInvalidUsernameDialog 可能有问题。

标签: flutter dart flutter-layout


【解决方案1】:

直接使用 catch 并检查其是否为 DioError 类型。这是一个已知的行为.. 它没有捕获 400 或 500 个错误

https://github.com/flutterchina/dio/issues/1198

try{

}catch(e){
 print(e.toString()); 
}

或者

try{
}catch(e){
 if(e is DioError)
 {
 }
}

【讨论】:

  • OP 显示了一个堆栈跟踪,清楚地显示了DioErrorusing unqualified catch (e) clauses is a bad idea,因为它会捕获很多不应该被捕获的东西(包括Errors,例如AssertionError)。
  • 更新了我的答案。谢谢你让我知道@jamesdlin
  • 更新后的答案仍然吞噬了不是DioError 的所有内容,这很糟糕。而且,如前所述,堆栈跟踪清楚地表明 DioError抛出。
  • 我不知道为什么,但是您的原始版本显示了我的弹出窗口,而编辑后的版本忽略了它。原则上,我对此完全满意。但如果jamesdlin 有不同的解决方案,那么我暂时不会结束这个问题。
  • stackoverflow.com/questions/57455741/…@jamesdlin 请查看此内容。您在评论中添加的链接也将我带到流媒体。
【解决方案2】:

发送API请求时可以使用error_handler捕获各种错误

这是一个例子:

import 'package:dio/dio.dart';
import 'package:error_handler/error_handler.dart';
import 'post.dart';

/// first create [Dio] api call
FutureResponse<Post> getPost() async {
  final dio = Dio();

  final response =
      await dio.get("https://jsonplaceholder.typicode.com/posts/1");

  return HttpResponse(Post.fromJson(response.data), response);
}

/// wrap the api call with [safeApiCall]
void main() {
  safeApiCall(getPost).listen((event) {
    event.when(
      idle: () {
        print("init");
      },
      loading: () {
        print("loading...");
      },
      data: (post, statusCode) {
        print("title: ${post.title}");
      },
      error: (error) {
        print(getErrorMessage(error));
      },
    );
  });
}

【讨论】:

    猜你喜欢
    • 2021-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-01
    • 2017-06-12
    • 2023-02-05
    • 1970-01-01
    • 2015-07-11
    相关资源
    最近更新 更多