You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;
        }
      }
    }
  });
}

问题原因

  1. 函数未返回有效结果:CheckHistory是async函数,但内部调用colRef.get().then(...)时,没有把这个Promise返回出去。then回调里的return只是回调自身的返回值,不会成为外层函数的返回值,导致函数默认返回一个resolved为undefined的Promise。
  2. 控制台打印对象错误:调用代码里console.log(CheckHistory)是直接打印函数本身,而非await后得到的结果hist,这才会出现[AsyncFunction: CheckHistory]的输出。
  3. 隐性代码问题:
    • 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 00:05:11