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

如何解决嵌套Firebase查询产生的Promise无法及时resolve的问题?

问题诊断
  • 错误使用onSnapshot方法:onSnapshot是 Firestore 的实时监听器,不返回 Promise,await 对它完全无效。你的代码会在绑定监听器后立刻执行return Promise.all(test),此时所有用户信息的查询请求还没返回,test数组是空的,自然拿不到数据。
  • Promise 收集逻辑错误:你没有把firestore.collection("users").doc(user).get()返回的 Promise 存入test数组,而是等查询成功后才把会话对象 push 进数组,Promise.all监听的是空数组,会直接 resolve 空结果。
  • 内存泄漏风险:onSnapshot绑定的监听器没有在组件卸载时取消,会导致内存泄漏,如果你只需要单次拉取数据,完全不需要用监听器,改用get()方法即可。
优化实现方案

如果你只需要单次拉取会话和对应用户数据,可以直接使用修正后的代码:

const conversationsRef = firestore.collection("conversations").where("users", "array-contains", auth.currentUser.uid).orderBy("updatedAt", "desc");
const [convo, set] = useState([]);

async function getConversations(){
    // 单次拉取会话列表,get方法会返回Promise
    const snap = await conversationsRef.get();
    // 收集所有用户信息查询的Promise
    const userQueryPromises = [];
    snap.forEach(doc => {
        const conversation = doc.data();
        // 筛选出会话中除当前用户外的目标用户id
        const targetUserId = conversation.users.find(user => user !== auth.currentUser.uid);
        if(targetUserId){
            // 将查询Promise存入数组,查询完成后返回挂载了用户信息的会话对象
            const userQuery = firestore.collection("users").doc(targetUserId).get().then(userProfile => {
                conversation.po = userProfile.data();
                return conversation;
            });
            userQueryPromises.push(userQuery);
        }
    });
    // 等待所有用户查询完成后返回完整会话列表
    return Promise.all(userQueryPromises);
}

useEffect(()=>{
    getConversations().then(data => {
        console.log(data);
        console.log(data[0]?.hostId);
        setActiveChat(data[0]);
        set(data);
    });
},[])

如果需要保持会话的实时更新,可以使用监听器版本的实现,同时添加卸载逻辑避免内存泄漏:

useEffect(() => {
    // 绑定实时监听器,返回取消监听的函数
    const unsubscribe = conversationsRef.onSnapshot(async snap => {
        const userQueryPromises = [];
        snap.forEach(doc => {
            const conversation = doc.data();
            const targetUserId = conversation.users.find(user => user !== auth.currentUser.uid);
            if(targetUserId){
                const userQuery = firestore.collection("users").doc(targetUserId).get().then(userProfile => {
                    conversation.po = userProfile.data();
                    return conversation;
                });
                userQueryPromises.push(userQuery);
            }
        });
        const data = await Promise.all(userQueryPromises);
        setActiveChat(data[0]);
        set(data);
    });
    // 组件卸载时取消监听
    return () => unsubscribe();
}, [])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 09:45:03