React异步函数调用Firestore set时,如何让onSnapshot回调按预期执行?
问题:Firestore onSnapshot 回调执行顺序异常
我当前代码的简化版本如下:
export const setTimestamp = async () => { console.log("START") let result = null; const dbRef = await firestore.collection("collectionName").doc("docName"); const unsub = await dbRef.onSnapshot(snap => { result = snap.data(); console.log("ACTUAL END", result); }); await dbRef.set({ serverTime: firebase.firestore.FieldValue.serverTimestamp() }); unsub(); console.log("FUNCTION END", result); return result; };
目前FUNCTION END会在ACTUAL END之前打印,而我需要两者顺序相反(先输出ACTUAL END,再输出FUNCTION END)。请问有解决思路吗?是否存在onSnapshot的替代方案?
解决思路
这个问题的核心是**onSnapshot的回调是异步触发的**:你调用set()后立刻执行的unsub()和console.log("FUNCTION END")属于同步代码,会先于快照更新的回调执行,所以才出现了顺序颠倒的情况。下面给你两种可行的解决方式:
方式一:用Promise包装监听,等待目标更新触发回调
把onSnapshot的逻辑包裹在Promise中,只有当捕获到set()后的更新快照时才resolve,以此保证执行顺序:
export const setTimestamp = async () => { console.log("START") const dbRef = firestore.collection("collectionName").doc("docName"); // 用Promise包装监听,等待set后的更新快照 const updatedData = await new Promise((resolve) => { const unsub = dbRef.onSnapshot(snap => { const data = snap.data(); // 过滤初始快照,只处理包含serverTime的更新结果 if (data?.serverTime) { console.log("ACTUAL END", data); unsub(); // 获取结果后取消监听 resolve(data); } }); }); await dbRef.set({ serverTime: firebase.firestore.FieldValue.serverTimestamp() }); console.log("FUNCTION END", updatedData); return updatedData; };
这里加data?.serverTime判断是为了避免onSnapshot初始触发的旧数据干扰,确保只处理set()后的最新结果。
方式二:用get()替代onSnapshot(适合单次获取场景)
如果你只需要获取set()完成后的文档最新数据,不需要持续监听变化,完全可以用get()替代onSnapshot,逻辑更简洁:
export const setTimestamp = async () => { console.log("START") const dbRef = firestore.collection("collectionName").doc("docName"); // 先执行set操作 await dbRef.set({ serverTime: firebase.firestore.FieldValue.serverTimestamp() }); // 主动拉取更新后的文档数据 const snap = await dbRef.get(); const result = snap.data(); console.log("ACTUAL END", result); console.log("FUNCTION END", result); return result; };
这种方式下,set()完成后主动获取最新数据,能完全保证你需要的执行顺序,还省去了监听取消的步骤。
内容的提问来源于stack exchange,提问作者Joseph Beuys' Mum
相关产品推荐
相关产品推荐

