从Firebase Firestore查询时如何从Promise中提取变量(JavaScript)
问题分析
你的核心问题是没搞懂异步操作和Promise的工作逻辑:
db.collection(...).get()是异步方法,它不会卡住代码等待数据库返回结果,函数pullIt会先执行完,而数据库请求还在后台跑,所以你在函数外部访问savedArrayUID时,数据根本还没被填充进去。- 你在
forEach里写的return savedArrayUID完全没用,这个return只对forEach的回调函数生效,根本传不到pullIt函数外面。
解决方案
别用全局数组存数据,让pullIt直接返回一个Promise,后续通过then或者async/await来拿查询结果,这才是异步操作的正确姿势。
方案1:返回Promise,用then处理结果
function pullIt(emailSearch) { // 返回get()的Promise链,把查询结果带出去 return db.collection(collectionName).where('email', '==', emailSearch).get() .then((querySnapshot) => { const savedArrayUID = []; const savedArrayEmails = []; querySnapshot.forEach((doc) => { savedArrayUID.push(doc.id); savedArrayEmails.push(doc.data()); console.log(doc.id, " => ", doc.data()); }); // 把两个数组打包成对象返回 return { uidList: savedArrayUID, userData: savedArrayEmails }; }); } // 调用方式: pullIt("example@xxx.com") .then(result => { console.log("查到的UID列表:", result.uidList); console.log("查到的用户资料:", result.userData); // 在这里处理数据,比如渲染页面、存到本地状态里 }) .catch(error => { console.error("查询出错:", error); });
方案2:用async/await简化同步写法
如果你习惯同步代码的逻辑,可以用async/await来包装:
async function pullIt(emailSearch) { try { // 用await等待数据库请求完成 const querySnapshot = await db.collection(collectionName).where('email', '==', emailSearch).get(); const savedArrayUID = []; const savedArrayEmails = []; querySnapshot.forEach((doc) => { savedArrayUID.push(doc.id); savedArrayEmails.push(doc.data()); console.log(doc.id, " => ", doc.data()); }); return { uidList: savedArrayUID, userData: savedArrayEmails }; } catch (error) { console.error("查询出错:", error); throw error; // 把错误抛出去让调用方处理 } } // 调用方式: async function getUserInfo() { try { const result = await pullIt("example@xxx.com"); console.log("查到的UID列表:", result.uidList); console.log("查到的用户资料:", result.userData); } catch (error) { // 在这里处理错误,比如提示用户查询失败 } } // 直接调用函数 getUserInfo();
关键提醒
- 别用全局变量存异步数据,容易出问题(比如多次调用
pullIt会把数据重复塞进数组),每次查询都新建数组更安全。 - 异步操作的结果只能通过Promise的回调或者
await获取,别想着用“等一下”的方式去拿,JavaScript的异步逻辑就是这么设计的。
内容的提问来源于stack exchange,提问作者Christian Bear
相关产品推荐
相关产品推荐

