使用getDocs获取数据库数据后,无法在then()外部访问数组数据
问题出在异步代码的执行顺序上
getDocs是异步请求,它不会阻塞后续代码执行——调用getDocs后,浏览器会继续运行后面的同步代码,而.then()里的逻辑要等数据库请求完成、拿到数据后才会触发。
你在.then()外面写的console.log(totalDB2['road1'])是同步代码,会比.then()里的赋值逻辑先执行,这时候totalDB2里还没数据,自然返回undefined。
另外提个小细节:你用数组totalDB2存键值对(用road1这种字符串当索引)不太合适,数组是用来存有序的数字索引数据的,换成普通对象{}更合理。
解决办法
办法1:把用数据的逻辑全放到.then()里
如果你的业务逻辑只需要在数据加载完后执行,直接把代码塞到.then()回调里就行:
const totalDBPromise2 = getDocs("Road"); let totalDB2 = {}; // 换成对象 totalDBPromise2.then((querySnapshot) => { querySnapshot.forEach((doc) => { const data = doc.data(); totalDB2[data.name] = data; // 对象直接赋值,不用判断includes }); console.log(totalDB2['road1']); // 正常拿到结果 // 所有需要用totalDB2的代码都写在这 });
办法2:用async/await写同步风格的异步代码
这个写法更直观,避免回调嵌套:
async function loadRoadData() { let totalDB2 = {}; // 等待getDocs请求完成 const querySnapshot = await getDocs("Road"); querySnapshot.forEach((doc) => { const data = doc.data(); totalDB2[data.name] = data; }); console.log(totalDB2['road1']); // 正常访问 // 后续用数据的逻辑都放这 } // 调用这个异步函数 loadRoadData();
办法3:把数据封装成Promise复用
如果多个地方需要用这份数据,可以把获取逻辑封装成函数,返回Promise:
function getRoadData() { return getDocs("Road").then((querySnapshot) => { const totalDB2 = {}; querySnapshot.forEach((doc) => { const data = doc.data(); totalDB2[data.name] = data; }); return totalDB2; }); } // 要用的时候再调用 getRoadData().then((totalDB2) => { console.log(totalDB2['road1']); // 写业务逻辑 });
提醒
- 别再用数组存键值对了,对象或者
Map才是干这个的,符合JS的规范。 - 异步请求的结果只能在异步回调(
.then()里、await之后)里靠谱地拿到,同步代码抢在异步请求完成前跑,肯定拿不到数据。
内容的提问来源于stack exchange,提问作者노경현
相关产品推荐
相关产品推荐

