Node.js Firestore异步函数无法返回MessageEmbed数组问题排查
问题:使用await调用异步函数CheckHistory未返回预期数组,控制台打印[AsyncFunction: CheckHistory]
我用Firebase查询用户处罚记录,调用异步函数CheckHistory时已经用了await,但函数没返回预期的MessageEmbed数组,控制台打印出[AsyncFunction: CheckHistory]。相关信息如下:
1. 控制台输出
[AsyncFunction: CheckHistory]
2. 调用代码
let hist = await CheckHistory(id); console.log(CheckHistory);
3. 函数代码
async function CheckHistory(user){ CheckBan(user); let historyArray = []; const colRef = db.collection('punishments') colRef.where('user', '==', user).get().then(async querySnapshot => { length = querySnapshot.size; if (querySnapshot.empty){ console.log(querySnapshot.size) return 0; } else { let docs = querySnapshot.docs; for (let documentSnapshot of docs) { const revoke = documentSnapshot.get('revoke') let active = documentSnapshot.get('active') if (active = true){ active = "Active" } else { active = `Revoked for ${revoke}` } const mod = documentSnapshot.get('mod') const reason = documentSnapshot.get('reason'); const time = documentSnapshot.get('time'); let type = documentSnapshot.get('type'); if (type == 1){ type = "Blacklist"; } else if (type == 2){ type = "Dayban"; } else if (type == 3){ type = "Warning"; } const username = await API.getUsernameFromId(user); const modname = await API.getUsernameFromId(mod); const historyEmbed = new MessageEmbed() .setColor('#0099ff') .setTitle(`'Punishment of ${username}:${user}`) .setDescription(`This is a punishment log.`) .addFields( { name: 'Status', value: `${active}`}, { name: 'Moderator', value: `${modname}:${mod}` }, { name: 'Reason', value: `${reason}` }, { name: 'Type', value: `${type}` }, { name: 'Time', value: `<t:${time}>`} ) historyArray.push(historyEmbed); if (historyArray.length >= length) { return historyArray; } } } }); }
问题原因
- 函数未返回有效结果:
CheckHistory是async函数,但内部调用colRef.get().then(...)时,没有把这个Promise返回出去。then回调里的return只是回调自身的返回值,不会成为外层函数的返回值,导致函数默认返回一个resolved为undefined的Promise。 - 控制台打印对象错误:调用代码里
console.log(CheckHistory)是直接打印函数本身,而非await后得到的结果hist,这才会出现[AsyncFunction: CheckHistory]的输出。 - 隐性代码问题:
active = true是赋值操作,不是相等判断,应该写成active === true或者直接if (active)length变量未声明,会污染全局作用域- 如果
CheckBan(user)是异步函数,未加await会导致后续代码提前执行
解决方法
1. 修复调用代码
把打印对象改成hist,查看函数返回的实际结果:
let hist = await CheckHistory(id); console.log(hist); // 打印函数返回的结果,而非函数本身
2. 重构CheckHistory函数
用await替代.then(),让异步逻辑更清晰,同时确保函数返回正确结果:
async function CheckHistory(user){ // 如果CheckBan是异步函数,必须加await await CheckBan(user); let historyArray = []; const colRef = db.collection('punishments'); const querySnapshot = await colRef.where('user', '==', user).get(); // 用await获取查询结果 const length = querySnapshot.size; // 声明length变量,避免全局污染 if (querySnapshot.empty){ console.log(querySnapshot.size); return 0; // 无记录时返回0 } else { let docs = querySnapshot.docs; for (let documentSnapshot of docs) { const revoke = documentSnapshot.get('revoke'); // 修复判断逻辑,直接用布尔值判断 let active = documentSnapshot.get('active') ? "Active" : `Revoked for ${revoke}`; const mod = documentSnapshot.get('mod'); const reason = documentSnapshot.get('reason'); const time = documentSnapshot.get('time'); // 用switch替代多分支if,提升可读性 let type = documentSnapshot.get('type'); switch(type) { case 1: type = "Blacklist"; break; case 2: type = "Dayban"; break; case 3: type = "Warning"; break; default: type = "Unknown"; // 处理未知类型 } const username = await API.getUsernameFromId(user); const modname = await API.getUsernameFromId(mod); const historyEmbed = new MessageEmbed() .setColor('#0099ff') .setTitle(`Punishment of ${username}:${user}`) // 去掉多余的单引号 .setDescription(`This is a punishment log.`) .addFields( { name: 'Status', value: active }, { name: 'Moderator', value: `${modname}:${mod}` }, { name: 'Reason', value: reason }, { name: 'Type', value: type }, { name: 'Time', value: `<t:${time}>`} ); historyArray.push(historyEmbed); } return historyArray; // 遍历完所有记录后返回数组 } }
关键修改说明
- 用
await替代.then(),让异步逻辑线性化,确保函数能返回包含查询结果的Promise - 修复
active的判断错误,避免赋值操作替代判断逻辑 - 声明
length变量,避免全局作用域污染 - 循环结束后直接返回数组,无需额外判断长度(循环会遍历所有文档)
- 修复标题中的多余单引号问题
- 用
switch优化类型判断逻辑,提升代码可读性
内容的提问来源于stack exchange,提问作者Charley
相关产品推荐
相关产品推荐

