MongoDB异步Cursor导致权限校验函数提前返回,无法正确返回校验结果的问题
问题分析与解决方案
你遇到的核心问题是异步代码的执行顺序问题。toArray()是一个异步方法,它的回调函数会在数据库查询完成后才被调用,但你的函数会先同步执行完所有非异步代码(也就是console.log("5 return here")这部分),然后函数就结束了——甚至你的原函数都没有返回access变量!等数据库查询完成、回调里的权限校验逻辑执行时,函数早就已经执行完毕,自然没法拿到正确的校验结果,这就是控制台输出顺序是1 5 return here 2 3 3 3 4的原因。
另外你的权限校验逻辑还有个小问题:循环里的return会导致只要遇到第一个不匹配的用户ID就直接终止检查,漏掉后续可能匹配的权限项,这会导致权限判断不准确。
下面是修正后的代码,我用async/await来处理异步操作,同时修正了逻辑问题:
async function permissionChecker(guildID, reqUserID, checkPexArray) { console.log("1") let access = false // 用await等待数据库查询完成,替代回调函数 try { const result = await db.db("MainDB").collection("Permissions").find({GuildID: guildID}).toArray(); console.log("2") if (!result || result.length === 0) { // 如果没有找到对应服务器的权限配置,直接返回false return access; } const serverDB = result[0]; const serverPexUsers = serverDB.PexUsers; // 遍历需要检查的权限项 for (const reqPex of checkPexArray) { // 检查当前权限项是否存在于用户权限列表中 if (serverPexUsers.hasOwnProperty(reqPex)) { // 检查当前用户ID是否在该权限项的用户列表里 if (serverPexUsers[reqPex].includes(reqUserID)) { console.log("4") access = true; // 只要找到一个匹配的权限,就可以提前返回true return access; } } } // 遍历完所有权限都没匹配,返回false return access; } catch (err) { console.error("数据库查询出错:", err); return false; } }
关键改动说明:
- 把函数改成
async函数,用await等待toArray()的结果,这样代码会按顺序执行,不会跳过异步逻辑。 - 移除了回调函数,改用
try/catch处理数据库查询可能出现的错误。 - 修正了权限校验逻辑:只要找到任意一个匹配的权限项,就返回
true;遍历完所有项都没匹配才返回false,避免了原逻辑中提前终止检查的问题。 - 增加了对查询结果为空的判断,避免后续代码出现
undefined错误。
调用方式:
因为这是async函数,调用时需要用await或者.then()来获取结果:
// 用await调用(需要在async函数中) const hasAccess = await permissionChecker("你的服务器ID", "用户ID", ["需要检查的权限1", "权限2"]); // 或者用.then() permissionChecker("你的服务器ID", "用户ID", ["需要检查的权限1", "权限2"]) .then(hasAccess => { console.log("权限校验结果:", hasAccess); }) .catch(err => { console.error("校验出错:", err); });
这样就能保证权限校验逻辑执行完成后才返回结果,不会出现异步代码被跳过的情况了。
内容的提问来源于stack exchange,提问作者Влад Пекарь
相关产品推荐
相关产品推荐

