You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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();
    }
  }
}

问题分析

  1. 异常捕获范围不足:当前代码仅捕获Exception类型异常,但iOS端浏览器可能抛出非Exception类型的错误(如Error子类、网络层面特定错误),这些错误会被第二个空catch(error)块捕获但未处理,导致gatewayDetected仍为'ok',弹窗无法触发。
  2. CORS跨域限制:iPad端浏览器对跨域请求管控更严格,若1880端口的后端服务未配置CORS,PC端Chrome可能因调试环境宽松允许请求,但iOS端会直接拦截,且抛出的异常不在Exception范围内。
  3. 网络请求无超时处理: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 21:34:54