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

Firebase Firestore无网络时Promise未触发catch问题求助(React Native/Expo)

问题原因与解决方案

兄弟,这个问题其实是Firestore离线持久化的默认行为在搞鬼,不是你漏了基础知识~

核心原因

Firebase Firestore在React Native/Expo环境中默认开启了离线持久化功能。当你调用docRef.get()时:

  • 如果设备离线,且本地缓存中没有这个文档的副本,Firestore会一直挂起这个Promise,等待网络恢复后再尝试从服务器获取数据,不会立即触发catch回调。
  • 只有当网络请求明确失败(比如联网但服务器返回错误),或者你指定了读取来源且来源不可用时,才会进入catch。

解决办法

你可以通过以下几种方式处理这种情况:

1. 指定读取来源

调用get()时通过source参数明确指定读取缓存还是服务器:

  • 只想读缓存:如果缓存里没有该文档,会直接触发catch
docRef.get({ source: 'cache' })
  .then((doc) => {
    if (doc.exists) {
      // 处理缓存中的数据
    } else {
      // 缓存中无此文档
      alert('No cached data available');
    }
  })
  .catch(() => {
    alert('Please connect to the internet');
  });
  • 强制读服务器:离线时会直接触发catch
docRef.get({ source: 'server' })
  .then(() => { /* 处理服务器数据 */ })
  .catch(() => {
    alert('Please connect to the internet');
  });

2. 先检查网络状态

在调用get()前,先通过Expo的Network模块检查设备是否联网:

import * as Network from 'expo-network';

// 先检查网络
const checkNetwork = async () => {
  const networkState = await Network.getNetworkStateAsync();
  if (!networkState.isConnected) {
    alert('Please connect to the internet');
    return false;
  }
  return true;
};

// 使用示例
checkNetwork().then((isConnected) => {
  if (isConnected) {
    docRef.get()
      .then(() => { /* 处理数据 */ });
  }
});

3. 给Promise添加超时

如果不想无限等待,可以自己封装一个带超时的Promise,和Firestore的请求一起用Promise.race:

const withTimeout = (promise, timeoutMs) => {
  return Promise.race([
    promise,
    new Promise((_, reject) => {
      setTimeout(() => reject(new Error('Request timed out')), timeoutMs);
    })
  ]);
};

// 使用示例
withTimeout(docRef.get(), 5000) // 5秒超时
  .then(() => { /* 处理数据 */ })
  .catch(() => {
    alert('Please connect to the internet');
  });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:04:48