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

FirebaseError: Quota exceeded:如何正确关闭Firebase的snapShot监听器

问题根因
  • 你的代码未处理组件提前卸载的场景:如果组件在1秒的定时器触发前就被卸载,unsubscribe 方法永远不会执行,监听器会持续在后台运行,持续产生读请求消耗配额
  • React 开发环境默认开启严格模式(StrictMode)时,组件会执行两次挂载逻辑,相当于单次页面加载就会创建2个独立的监听器,开发过程中频繁热重载更新代码的话,泄漏的监听器会快速堆叠,很快耗尽免费配额
  • 即使你主动调用了unsubscribe,onSnapshot在绑定成功的瞬间就会触发一次全量读取,如果你页面切换频繁,每次进入都触发一次全量读取,也会快速累加读请求次数
修复方案
  • 补全useEffect的清空逻辑,不管定时器有没有触发,组件卸载时都直接关闭监听器,同时清空定时器避免内存泄漏,修改后的代码如下:
useEffect(() => {
    console.log("Loading snapShots on firebase");
   const unsubscribe = db.collection('chats').onSnapshot(snapshot => (
        setChats(snapshot.docs.map(doc => ({
            id: doc.id,
            data: doc.data()
        })))
    ))
    const timer = setTimeout(()=>{
         unsubscribe();
    }, 1000);
    // 新增组件卸载时的清空逻辑
    return () => {
      clearTimeout(timer)
      unsubscribe()
    }
}, [])
  • 如果你的业务场景不需要实时更新聊天数据,只需要进入页面拉取一次,直接替换onSnapshot为单次get请求,完全不需要处理监听器逻辑,消耗的配额只有单次读取:
useEffect(() => {
  const getChats = async () => {
    console.log("Loading chats from firebase");
    const snapshot = await db.collection('chats').get();
    setChats(snapshot.docs.map(doc => ({
      id: doc.id,
      data: doc.data()
    })))
  }
  getChats()
}, [])
  • 开发阶段可以暂时关闭React严格模式,避免重复挂载产生多余的监听器和读请求
  • 登陆Firebase控制台,进入Firestore的使用统计页面,查看具体的读请求消耗明细,确认是否有其他未关闭的监听器在持续产生请求

内容的提问来源于stack exchange,提问作者Tercé Nicolas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 10:36:00