MongoExpiredSessionError排查:循环调用findOne致会话已结束
问题原因与解决方案
核心问题
- forEach不支持异步等待:你用
forEach遍历执行异步查询,但forEach不会等待内部的async回调完成,导致getChildrenDetails函数直接返回空数组,后续异步查询执行时,数据库会话(session)已被关闭,触发MongoExpiredSessionError。 - 数组push操作错误:代码里写的
childrenListWithDetails.push = childWithDetails是语法错误,正确调用应为childrenListWithDetails.push(childWithDetails)。 - findOne参数误用:原代码把
roll_no放到了投影参数(第二个参数)里,实际上要同时匹配class和roll_no,需将两者都放入第一个查询条件参数中。
修正方案
方案一:for...of循环(顺序执行)
适合对查询顺序有要求的场景,逐个等待查询完成:
async function getChildrenDetails(client, instituteDatabase, childrenList) { let childrenListWithDetails = []; for (const child of Object.keys(childrenList)) { const childClassAndRollNo = childrenList[child]; const childWithDetails = await client .db(instituteDatabase) .collection("student") .findOne({ class: childClassAndRollNo.class, roll_no: childClassAndRollNo.roll_no }); childrenListWithDetails.push(childWithDetails); } return childrenListWithDetails; }
方案二:Promise.all(并行执行,效率更高)
无需顺序执行时,用此方法同时发起所有查询,性能更优:
async function getChildrenDetails(client, instituteDatabase, childrenList) { const detailPromises = Object.keys(childrenList).map(async (child) => { const childClassAndRollNo = childrenList[child]; return client .db(instituteDatabase) .collection("student") .findOne({ class: childClassAndRollNo.class, roll_no: childClassAndRollNo.roll_no }); }); return Promise.all(detailPromises); }
内容的提问来源于stack exchange,提问作者Khanday Ovais
相关产品推荐
相关产品推荐

