JavaScript中console.log输出sum1为undefined的原因及解决建议
为什么console.log(sum1)返回undefined?
问题出在异步执行顺序上:onSnapshot是Firestore的实时监听函数,它的回调是异步执行的——你的代码会先执行console.log(sum1),然后才会触发onSnapshot的回调去给sum1赋值。这时候sum1还没被赋值,自然输出undefined。
解决方案
1. 直接在回调内使用sum1(最适合实时监听场景)
把需要用到sum1的逻辑(比如console.log)放到onSnapshot的回调函数里,确保在sum1被赋值后再执行:
var sum1; const q = query(collection(db, "users"),where("selected", "==", "Gasto"), where("moneda", "==", "$")); const unsubscribe = onSnapshot(q,(querySnapshot) => { const dolarCurrency = []; const months =[]; querySnapshot.forEach((doc) =>{ dolarCurrency.push(doc.data().cantidad); months.push(doc.data().fecha) }) const hash = months.map((Day) => ({ Day })); const hashDolar = dolarCurrency.map(( Amount ) => ({ Amount })) const output = hash.map(({Day},i) => ({Day, ...hashDolar[i]})); sum1 = output.reduce((acc, cur)=> { const found = acc.find(val => val.Day === cur.Day) if(found){ found.Amount+=Number(cur.Amount) } else{ acc.push({...cur, Amount: Number(cur.Amount)}) } return acc }, []) // 此时sum1已完成赋值,可正常使用 console.log(sum1); return sum1; })
2. 用Promise封装(适合只需要一次数据的场景)
如果不需要实时监听,只是想获取一次数据后处理,可以用getDocs代替onSnapshot,并把逻辑包成Promise,用async/await等待结果:
function fetchSum1() { return new Promise((resolve) => { const q = query(collection(db, "users"),where("selected", "==", "Gasto"), where("moneda", "==", "$")); getDocs(q).then((querySnapshot) => { const dolarCurrency = []; const months =[]; querySnapshot.forEach((doc) =>{ dolarCurrency.push(doc.data().cantidad); months.push(doc.data().fecha) }) const hash = months.map((Day) => ({ Day })); const hashDolar = dolarCurrency.map(( Amount ) => ({ Amount })) const output = hash.map(({Day},i) => ({Day, ...hashDolar[i]})); const sum1 = output.reduce((acc, cur)=> { const found = acc.find(val => val.Day === cur.Day) if(found){ found.Amount+=Number(cur.Amount) } else{ acc.push({...cur, Amount: Number(cur.Amount)}) } return acc }, []) resolve(sum1); }); }); } // 调用并打印结果 async function logSum1() { const sum1 = await fetchSum1(); console.log(sum1); } logSum1();
额外提示
如果确实需要实时监听数据变化,记得在组件卸载或不需要监听时调用unsubscribe(),避免内存泄漏。
内容的提问来源于stack exchange,提问作者Robert Grootjen
相关产品推荐
相关产品推荐

