Firebase异步读取后返回符合条件数组的实现问题
解决Firebase异步查询后返回数组的问题
你的问题核心在于 异步操作的执行顺序:query.once("value")是异步任务,它的then回调会在当前函数的同步代码执行完之后才运行。所以你直接return listOfItems的时候,forEach还没开始遍历数据,数组自然是空的。
要解决这个问题,我们需要让函数返回一个Promise,把异步操作的结果通过Promise传递出去,这样调用方就能在异步操作完成后拿到正确的数组。
方案1:修改函数返回Promise
直接把数据库查询的Promise链返回出去,在then里处理完数据后返回数组:
exports.getNearbyPosts = function (myLat, myLng){ var query = firebase.database().ref("posts/").orderByKey(); // 返回整个Promise链 return query.once("value") .then(function(snapshot) { var listOfItems = []; snapshot.forEach(function(childSnapshot) { var childData = childSnapshot.val(); var dist = getDistanceBetweenCoord(childData.lat, childData.lng, myLat, myLng); if(dist < 10239820938502){ listOfItems.push(childSnapshot); } }); // 在这里返回处理好的数组,它会成为Promise的resolve值 return listOfItems; }); }
调用方式
你需要通过then或者await来获取结果:
// 方式1:使用then回调 getNearbyPosts(你的纬度, 你的经度).then(function(nearbyPosts) { // 这里就能拿到完整的数组了 console.log("附近帖子:", nearbyPosts); // 在这里做后续操作,比如渲染到页面 }); // 方式2:在async函数中使用await async function loadNearbyPosts() { const nearbyPosts = await getNearbyPosts(你的纬度, 你的经度); console.log("附近帖子:", nearbyPosts); } loadNearbyPosts();
方案2:用async/await简化代码
如果你习惯更同步化的写法,可以用async/await改写函数,让代码逻辑更清晰:
exports.getNearbyPosts = async function (myLat, myLng){ var query = firebase.database().ref("posts/").orderByKey(); // 用await等待异步查询完成 const snapshot = await query.once("value"); var listOfItems = []; snapshot.forEach(function(childSnapshot) { var childData = childSnapshot.val(); var dist = getDistanceBetweenCoord(childData.lat, childData.lng, myLat, myLng); if(dist < 10239820938502){ listOfItems.push(childSnapshot); } }); // 直接返回数组,async函数会自动把它包装成Promise return listOfItems; }
调用方式和方案1完全一样,因为async函数本身就返回一个Promise。
关键知识点
JavaScript中,异步操作的结果无法同步返回,必须通过Promise(或者回调函数,但Promise更现代)来传递结果。你原来的代码试图同步返回异步操作的结果,这必然会拿到空数组,因为异步任务还没执行呢。
内容的提问来源于stack exchange,提问作者Annie Zhou
相关产品推荐
相关产品推荐

