Flutter Web如何获取XMLHttpRequest错误详情?
针对你在Flutter Web + graphql-flutter中遇到的底层错误区分问题,可以通过拆解异常链+Web平台原生HttpRequest信息来精准判断错误类型,下面是具体实现方案:
错误类型区分思路
graphql-flutter的错误层级为:OperationException → LinkException → Web平台原生ProgressEvent。像连接超时、连接拒绝这类底层网络错误,实际藏在LinkException.originalException对应的ProgressEvent里,我们可以通过这个事件关联的HttpRequest对象获取更细节的错误信息。
具体实现代码
先通过条件导入Web平台的dart:html库(避免跨平台编译问题),再编写错误判断工具类:
import 'package:graphql_flutter/graphql_flutter.dart'; // 条件导入Web平台专属库,非Web平台会导入dart:io占位 import 'dart:html' if (dart.library.io) 'dart:io' as platform; // 定义错误类型枚举,方便后续区分处理 enum GraphQLErrorType { connectionRefused, timeout, unknownHost, httpError, // 带HTTP状态码的错误,如401、500 graphQLError, // 服务端返回的GraphQL业务错误 unknown, } GraphQLErrorType getGraphQLErrorType(QueryResult result) { if (!result.hasException) { return GraphQLErrorType.unknown; } final exception = result.exception; // 优先处理GraphQL业务错误(非网络层错误) if (exception?.graphqlErrors.isNotEmpty == true) { return GraphQLErrorType.graphQLError; } // 处理网络/链路层面的错误 final linkException = exception?.linkException; if (linkException != null) { final originalException = linkException.originalException; // Web平台下,originalException是ProgressEvent类型 if (originalException is platform.ProgressEvent) { final request = originalException.target as platform.HttpRequest; // 连接拒绝、未知主机这类无有效HTTP状态码的错误,request.status会是0 if (request.status == 0) { final error = request.error; if (error != null) { final errorMsg = error.toString().toLowerCase(); // 匹配不同浏览器的错误信息关键字 if (errorMsg.contains('connection refused')) { return GraphQLErrorType.connectionRefused; } else if (errorMsg.contains('timeout')) { return GraphQLErrorType.timeout; } else if (errorMsg.contains('unknown host') || errorMsg.contains('dns')) { return GraphQLErrorType.unknownHost; } } return GraphQLErrorType.unknown; } else { // 有正常HTTP状态码的错误,归类为HTTP错误 return GraphQLErrorType.httpError; } } } return GraphQLErrorType.unknown; } // 示例:判断是否为连接拒绝错误 bool isConnectionRefused(QueryResult result) { return getGraphQLErrorType(result) == GraphQLErrorType.connectionRefused; } // 整合你原有的401判断逻辑 bool isGraphqlResultUnauthorized(QueryResult result) { if (getGraphQLErrorType(result) != GraphQLErrorType.httpError) { return false; } final linkException = result.exception?.linkException; if (linkException is HttpLinkParserException) { return linkException.response.statusCode == 401; } return false; }
注意事项
- 浏览器兼容性:不同浏览器对底层错误的描述文本有差异,比如Chrome的连接拒绝错误是
net::ERR_CONNECTION_REFUSED,Firefox是NetworkError: Connection refused,所以用关键字模糊匹配更稳妥。 - 跨平台兼容:如果应用需要支持移动端,必须用条件导入
dart:html,否则非Web平台会编译报错。 - GraphQL业务错误区分:这类错误是服务端返回的业务逻辑错误(如参数非法、权限不足),会存放在
OperationException.graphqlErrors中,可单独做业务处理。
内容的提问来源于stack exchange,提问作者Robert Estivill
相关产品推荐
相关产品推荐

