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

Flutter Web/PWA关闭标签或应用时调用API失败问题求助

关闭浏览器标签页/PWA时调用API失败问题

我尝试在用户关闭运行应用的标签页或已安装的PWA应用时调用API,但当前代码无法正常工作:

late String token;

setUserToken() async {
  token = await FirebaseAuth.instance.currentUser!.getIdToken(true);
}

@override
void initState() {
  super.initState();
  WidgetsBinding.instance.addObserver(this);
  // signOut();
  html.window.onBeforeUnload.listen((event) async {
    // do something
    print(token);
    print("closing");

    http.delete(
        Uri.parse(
          '${Helpers().apiUrl()}/location',
        ),
        headers: {
          'Authorization': 'Bearer $token',
          'Content-Type': 'application/json'
        });
  });
  setUserToken();
}

我也尝试过使用await http.delete。

补充说明

本地云函数调用该API时可以正常运行,但日志中出现以下内容:

2022-11-06T16:57:48.838Z OPTIONS /location
Function execution took 1936 ms. Finished with status code: 204


问题原因及修复方案

核心问题

  1. Token初始化时机问题:setUserToken是异步方法,initState中直接调用未等待完成,导致页面卸载触发事件时,token可能还未赋值,或者处于未初始化状态。
  2. 浏览器卸载事件的请求限制:普通http请求在onBeforeUnload事件中容易被浏览器中断,因为页面即将卸载,浏览器会主动终止未完成的网络请求。

具体修复步骤

  1. 触发事件时实时获取Token:避免依赖提前初始化的token,在事件触发时重新获取,既解决初始化时机问题,也能避免Token过期。
  2. 使用支持页面卸载的请求方式:改用浏览器的Fetch API并开启keepalive选项,确保请求能在页面卸载后完成。

修改后的代码:

@override
void initState() {
  super.initState();
  WidgetsBinding.instance.addObserver(this);
  
  html.window.onBeforeUnload.listen((event) async {
    // 实时获取有效Token
    final token = await FirebaseAuth.instance.currentUser!.getIdToken(true);
    print(token);
    print("closing");

    // 使用Fetch API并开启keepalive
    final apiUrl = '${Helpers().apiUrl()}/location';
    await html.fetch(apiUrl, {
      'method': 'DELETE',
      'headers': {
        'Authorization': 'Bearer $token',
        'Content-Type': 'application/json'
      },
      'keepalive': true, // 关键配置:告知浏览器保留请求直到完成
    });
  });
}

额外检查

  • CORS配置:虽然OPTIONS请求返回204(预检通过),但需确认服务器端允许带Authorization头的DELETE请求,响应头需包含Access-Control-Allow-Headers: Authorization, Content-Type。
  • 错误处理:可以给Fetch请求添加简单的错误捕获,方便排查问题:
    try {
      await html.fetch(apiUrl, { /* ...配置... */ });
    } catch (e) {
      print('卸载时请求失败: $e');
    }
    

内容的提问来源于stack exchange,提问作者AlienDecoy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 16:05:33