Firestore对象存入数组后按优先级数值键排序失败排查
问题分析与解决方案
我一眼就看出问题出在异步操作的执行时序上,这是JavaScript开发者很容易踩的坑!
核心问题:异步请求还没完成就执行了排序
你的代码里,db.collection("offers").doc(offer).get()是异步的Promise操作——forEach循环会同步跑完,但里面的.then()回调要等数据库请求完成后才会执行。而你在循环外直接调用offerpriority.sort(compare)和console.log,这时候offerpriority数组要么是空的,要么只填充了部分数据,排序自然不会生效。
另外,代码里第一行var offers = new Object;完全多余,后面马上用snap.data().offers重新赋值了,建议删掉。
修正方案:确保所有异步请求完成后再排序
下面提供两种可靠的解决方式,选哪种都可以:
方式1:用async/await让代码按顺序执行
把逻辑包裹在async函数里,用for...of替代forEach(forEach不支持await),确保每一个数据库请求完成后再继续下一步:
async function fetchAndSortOffers() { const offers = snap.data().offers; const offerpriority = []; // 用for...of循环,支持await等待异步请求完成 for (const offerId of offers) { const docSnap = await db.collection("offers").doc(offerId).get(); const thisOffer = { title: docSnap.data().title, pri: docSnap.data().priority }; offerpriority.push(thisOffer); } // 排序逻辑(你的compare函数是对的) function compare(a, b) { return b.pri - a.pri; }; offerpriority.sort(compare); console.log(offerpriority); // 取前三条用于仪表板展示 const topThreeOffers = offerpriority.slice(0, 3); console.log("Top 3 offers for dashboard:", topThreeOffers); } // 调用这个函数执行逻辑 fetchAndSortOffers();
方式2:用Promise.all批量处理异步请求
把所有数据库请求收集成Promise数组,等待全部完成后再处理排序,这种方式效率更高(并行请求):
const offers = snap.data().offers; // 把每个offer的请求转换成Promise对象 const offerPromises = offers.map(offerId => { return db.collection("offers").doc(offerId).get().then(docSnap => { return { title: docSnap.data().title, pri: docSnap.data().priority }; }); }); // 等待所有Promise完成后再排序 Promise.all(offerPromises).then(offerpriority => { function compare(a, b) { return b.pri - a.pri; }; offerpriority.sort(compare); console.log(offerpriority); // 取前三条用于展示 const topThreeOffers = offerpriority.slice(0, 3); console.log("Top 3 offers for dashboard:", topThreeOffers); });
两种方式都能确保offerpriority数组被完全填充后再执行排序,这样就能得到正确的结果,取前三条展示也没问题了。
内容的提问来源于stack exchange,提问作者James Patrick
相关产品推荐
相关产品推荐

