如何停止Firebase Firestore的数据库变更监听,解决请求挂起问题
问题根源
你当前使用的onSnapshot是Firebase Firestore提供的实时更新监听器,设计上就会保持长连接持续监听后端数据变更,所以请求会一直处于挂起状态,这是正常的功能特性而非故障。
你调用unsubscribe后拿不到数据的原因也很简单:onSnapshot的回调函数是异步执行的,你同步返回data、或是注册监听器后立刻调用unsubscribe时,回调还没来得及触发,数据数组还处于空的状态,自然拿不到返回值。
解决方案
根据你的使用场景二选一即可:
场景1:不需要实时更新,仅需一次性拉取数据
直接用一次性查询方法getDocs替换onSnapshot,拉取完成后连接会自动断开,不会有挂起的请求,是性能最优的方案:
// 改为异步函数,调用时需要配合await/then使用 const getData = async () => { const q = query(collection(firestore, "data"), where("published", "==", true)); const querySnapshot = await getDocs(q); const data = []; querySnapshot.forEach((doc) => { data.push({id: doc.id, ...doc.data()}); }); return data; }
场景2:需要使用实时监听,用完后再断开
控制unsubscribe的调用时机,不要注册后立刻取消。如果是在Next.js客户端组件中使用,可以配合useEffect生命周期管理,两种取消时机可以按需选择:
'use client' import { useEffect, useState } from 'react' const YourComponent = () => { const [data, setData] = useState([]) useEffect(() => { const q = query(collection(firestore, "data"), where("published", "==", true)); const unsubscribe = onSnapshot(q, (querySnapshot) => { const newData = [] querySnapshot.forEach((doc) => { newData.push({id: doc.id, ...doc.data()}); }); setData(newData) // 选择1:仅需要首次数据,拿到结果后立刻取消监听 unsubscribe() }); // 选择2:组件卸载时自动取消监听,适配需要持续监听的场景 return () => unsubscribe() }, []) // 后续渲染逻辑 }
调整后就能正常拿到数据,同时不会有长期挂起的Firestore请求。
内容的提问来源于stack exchange,提问作者Markus
相关产品推荐
相关产品推荐

