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

Firestore监听器在Safari失效,Chrome正常的问题求助

解决方案:Safari中Firestore实时监听器失效问题

问题根源

Safari对Firestore长轮询连接的处理逻辑与Chrome存在差异,可能因缓存旧会话ID(SID)、跨域策略限制或SDK兼容性问题,导致监听器请求返回Unknown SID错误。

具体修复步骤

1. 升级Firebase SDK到最新稳定版

旧版本Firebase SDK可能存在Safari兼容性bug,优先将firebase_core、cloud_firestore等依赖升级到pub.dev上的最新稳定版本,重新打包部署。

2. 修复监听器代码的异步错误+添加错误重试机制

原代码在listen回调内直接使用await会产生未处理的Future,且未处理监听器错误,导致Safari中连接中断后无法自动恢复。修改代码如下:

late StreamSubscription<QuerySnapshot>? _updatesSubscription; // 改为可空类型

@override
void initState() {
  super.initState();
  _listenForUpdates();
}

@override
void dispose() {
  _updatesSubscription?.cancel();
  super.dispose();
}

void _listenForUpdates() {
  // 先取消旧订阅,避免重复监听
  _updatesSubscription?.cancel();
  
  _updatesSubscription = FirebaseFirestore.instance
      .collection('updates')
      .snapshots()
      .listen(
    (snapshot) {
      for (var doc in snapshot.docChanges) {
        if (doc.type == DocumentChangeType.modified) {
          String updatedMasjidId = doc.doc.id;
          // 将异步操作抽离到单独函数
          _updateLocalPrayerTimes(updatedMasjidId);
          print('!!Update occurred for masjidId: $updatedMasjidId');
        }
      }
    },
    onError: (error) {
      print('Firestore listener error: $error');
      // 延迟5秒后重新启动监听,避免频繁重试
      Future.delayed(const Duration(seconds: 5), _listenForUpdates);
    },
  );
}

// 单独处理本地存储的异步更新
Future<void> _updateLocalPrayerTimes(String updatedMasjidId) async {
  await UserSettingsService.storePrayerTimesForCurrentMonth(
    [updatedMasjidId],
    [{'name': updatedMasjidId, 'id': updatedMasjidId}],
  );
}

3. 配置Firebase Hosting禁止缓存Firestore请求

Safari可能缓存了Firestore的旧会话请求,导致后续请求使用无效SID。在项目根目录的firebase.json中添加缓存控制规则:

{
  "hosting": {
    "headers": [
      {
        "source": "**/firestore/**",
        "headers": [
          {
            "key": "Cache-Control",
            "value": "no-cache, no-store, must-revalidate"
          }
        ]
      }
    ]
  }
}

修改后重新部署到Firebase Hosting:

firebase deploy --only hosting

4. 调整Firestore持久化设置(可选)

尝试关闭或开启Firestore的本地持久化,排查兼容性问题:

@override
void initState() {
  super.initState();
  // 初始化Firestore时配置持久化
  FirebaseFirestore.instance.settings = const Settings(
    persistenceEnabled: false, // 或改为true尝试
  );
  _listenForUpdates();
}

5. 提示用户检查Safari隐私设置(兜底方案)

部分用户可能开启了Safari的「阻止跨网站跟踪」功能,会干扰Firestore的长连接。可在应用内添加提示,引导用户临时关闭该设置或添加站点到例外列表。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 21:55:03