Flutter Web在iPad上Try/Catch的Catch块不触发(PC端正常)
Flutter Web iPad端AlertDialog不显示问题排查与解决
问题现象
用Flutter 3.13.7/Dart开发的Web应用,PC端Chrome中AlertDialog可正常触发显示;但iPad上的Safari或Chrome里,该弹窗始终无法显示。弹窗可见性由Provider中的gatewayDetected变量控制,值为'fail'时触发,疑似iOS端未按预期进入Try/Catch的Catch块,导致gatewayDetected未被设为'fail'。
相关代码
// HDLAN RX Status class HdlanRxStatus extends ChangeNotifier { List RxSnmpStatus = List.filled(48, '1'); List RxChSelect = List.filled(48, 'Search'); List sourceList = ['Cable1','Cable2','Cable3','Cable4','Cable5','Cable6']; int poeStatus = 1; // PoE wattage String switchIPAddress = ''; String gatewayDetected = 'ok'; String ciscoSwitchDetected = ''; getSnmpStatus() async { try{ print("http://${html.window.location.hostname.toString()}:1880/ciscoStat"); var response = await http.get(Uri.parse("http://${html.window.location.hostname.toString()}:1880/ciscoStat")); print(response.body); switchIPAddress = jsonDecode(response.body)["SwitchIPAddress"]; RxSnmpStatus = jsonDecode(response.body)["PortVlanMembership"]; // Update RX with Input Source Name RxSnmpStatus.asMap().forEach((index, item) => { RxChSelect[index] = sourceList[RxSnmpStatus[index]-2] }); poeStatus = jsonDecode(response.body)["PoE"]; ciscoSwitchDetected = jsonDecode(response.body)["PS1Stat"]; // 'OK' or 'link loss' gatewayDetected = 'ok'; }on Exception catch (e) { print(e); // Only catches an exception of type `Exception`. gatewayDetected = 'fail'; } catch(error){ }finally{ notifyListeners(); } } }
问题分析
- 异常捕获范围不足:当前代码仅捕获
Exception类型异常,但iOS端浏览器可能抛出非Exception类型的错误(如Error子类、网络层面特定错误),这些错误会被第二个空catch(error)块捕获但未处理,导致gatewayDetected仍为'ok',弹窗无法触发。 - CORS跨域限制:iPad端浏览器对跨域请求管控更严格,若1880端口的后端服务未配置CORS,PC端Chrome可能因调试环境宽松允许请求,但iOS端会直接拦截,且抛出的异常不在
Exception范围内。 - 网络请求无超时处理:iOS端网络环境不稳定时,请求可能挂起,既不触发异常也不返回结果,导致
gatewayDetected保持初始值。
解决方案
1. 补全异常处理逻辑
修改空catch(error)块,确保所有错误都能触发弹窗逻辑:
try{ // 原有请求代码 } on Exception catch (e) { print('Exception caught: $e'); gatewayDetected = 'fail'; } catch(error){ print('Error caught: $error'); // 打印所有类型错误,方便调试 gatewayDetected = 'fail'; // 统一设置为fail触发弹窗 } finally { notifyListeners(); }
2. 配置CORS跨域权限
给1880端口的后端服务添加CORS响应头,允许当前Web应用域名访问。以Node.js/Express为例:
app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', '*'); // 生产环境建议替换为具体域名 res.header('Access-Control-Allow-Methods', 'GET, OPTIONS'); res.header('Access-Control-Allow-Headers', 'Content-Type'); next(); });
iOS端对OPTIONS预检请求要求严格,需确保后端能正确响应。
3. 添加请求超时限制
避免请求因网络问题挂起,设置超时时间:
var response = await http.get( Uri.parse("http://${html.window.location.hostname.toString()}:1880/ciscoStat"), timeout: const Duration(seconds: 5), // 根据实际情况调整超时时间 );
4. 调试iOS端错误日志
打开iPad「设置」→「Safari浏览器」→「高级」→ 开启「Web检查器」;在Mac上打开Safari,通过顶部「开发」菜单选择连接的iPad及对应Web应用,查看控制台错误日志,明确具体抛出的异常类型。
内容的提问来源于stack exchange,提问作者sou pen su
相关产品推荐
相关产品推荐

