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

Express后端执行MySQL查询遇TypeError,求问题排查及错误处理方案

问题:Express中MySQL查询出现TypeError: Cannot read properties of undefined (reading 'word')

我在Express服务器中执行MySQL查询时遇到错误,负责生成每日单词组合的generateDailyWords函数代码如下:

module.exports.generateDailyWords = async function () {
  try {
    // generate the shape of word combination for the day
    var shape = generateRandomNumbers();

    // retrieve 4 words from the dictionary
    var q_1 = `
            SELECT word 
            FROM new_dic 
            WHERE LENGTH(word) = ?
            ORDER BY RAND() 
            LIMIT 1
        `;
    var first = await excuteQuery(q_1, [shape[0]]);
    var word_1 = first[0].word;

    var q_2 = `
            SELECT word 
            FROM new_dic 
            WHERE LENGTH(word) = ? 
            AND word LIKE ?
            AND word != ?
            ORDER BY RAND() 
            LIMIT 1
        `;

    var second = await excuteQuery(q_2, [shape[1], word_1[0] + "%", word_1]);
    var word_2 = second[0].word;

    var q_3 = `
            SELECT word 
            FROM new_dic 
            WHERE LENGTH(word) = ? 
            AND word LIKE ? 
            AND word != ?
            AND word != ?
            ORDER BY RAND() 
            LIMIT 1
        `;

    var third = await excuteQuery(q_3, [
      shape[1],
      word_1[word_1.length - 1] + "%",
      word_1,
      word_2,
    ]);
    var word_3 = third[0].word;

    var q_4 = `
            SELECT word
            FROM new_dic
            WHERE LENGTH(word) = ?
            AND word LIKE ?
            AND word != ?
            AND word != ?
            AND word != ?
            ORDER BY RAND()
            LIMIT 1
        `;

    var forth = await excuteQuery(q_4, [
      shape[0],
      word_2[word_2.length - 1] + "%" + word_3[word_3.length - 1],
      word_1,
      word_2,
      word_3,
    ]);
    var word_4 = forth[0].word;

    // save the combination into the database
    var combination = JSON.stringify([word_1, word_2, word_3, word_4]);

    return combination;
    // return '["jube","juicy","ender","ywar"]'
  } catch (err) {
    console.log(err, "err while generating daily words");
    await this.generateDailyWords();
  }
};

该函数定期运行(测试阶段每10分钟一次,正式环境改为每日一次),但有时会抛出错误:

TypeError: Cannot read properties of undefined (reading 'word')

打印查询返回的数据后发现,有时查询结果变量为undefined。我需要了解问题原因,以及后端错误处理的最佳实践(比如编写错误处理辅助函数的方法)。


问题原因

  • 查询无匹配结果:当executeQuery执行后返回的结果数组为空时,first[0]、second[0]等取值会是undefined,此时访问.word属性就会触发TypeError。比如:
    • shape生成的单词长度在字典表new_dic中没有对应数据;
    • 后续查询的过滤条件(比如LIKE前缀、排除已选单词)过于严格,没有符合条件的单词。
  • 无限制递归重试风险:当前catch块中直接递归调用generateDailyWords,如果连续多次查询无结果,会导致调用栈溢出,引发更严重的错误。

修复方案

1. 每次查询后校验结果+限制重试次数

在提取word属性前先检查查询结果,同时给重试逻辑加次数限制,避免栈溢出:

module.exports.generateDailyWords = async function (retryCount = 0) {
  const MAX_RETRIES = 5; // 限制最大重试次数
  try {
    const shape = generateRandomNumbers();

    // 封装查询单个单词的校验逻辑
    async function getWord(query, params) {
      const result = await excuteQuery(query, params);
      if (!result || result.length === 0) {
        throw new Error(`No matching word found for params: ${JSON.stringify(params)}`);
      }
      return result[0].word;
    }

    const word_1 = await getWord(`
      SELECT word 
      FROM new_dic 
      WHERE LENGTH(word) = ?
      ORDER BY RAND() 
      LIMIT 1
    `, [shape[0]]);

    const word_2 = await getWord(`
      SELECT word 
      FROM new_dic 
      WHERE LENGTH(word) = ? 
      AND word LIKE ?
      AND word != ?
      ORDER BY RAND() 
      LIMIT 1
    `, [shape[1], `${word_1[0]}%`, word_1]);

    const word_3 = await getWord(`
      SELECT word 
      FROM new_dic 
      WHERE LENGTH(word) = ? 
      AND word LIKE ? 
      AND word != ?
      AND word != ?
      ORDER BY RAND() 
      LIMIT 1
    `, [shape[1], `${word_1[word_1.length - 1]}%`, word_1, word_2]);

    const word_4 = await getWord(`
      SELECT word
      FROM new_dic
      WHERE LENGTH(word) = ?
      AND word LIKE ?
      AND word != ?
      AND word != ?
      AND word != ?
      ORDER BY RAND()
      LIMIT 1
    `, [shape[0], `${word_2[word_2.length - 1]}%${word_3[word_3.length - 1]}`, word_1, word_2, word_3]);

    const combination = JSON.stringify([word_1, word_2, word_3, word_4]);
    return combination;
  } catch (err) {
    console.error(`[Retry ${retryCount}] Error generating daily words:`, err.message);
    // 达到最大重试次数则抛出错误,避免栈溢出
    if (retryCount >= MAX_RETRIES) {
      throw new Error(`Failed to generate daily words after ${MAX_RETRIES} retries: ${err.message}`);
    }
    // 递归重试,次数+1
    return await this.generateDailyWords(retryCount + 1);
  }
};

2. 优化查询条件(可选)

  • 提前校验shape生成的长度是否在字典中有对应数据,避免无效查询;
  • 对于LIKE条件,如果前缀匹配无结果,可以放宽条件(比如改为包含该字符,或者直接随机选同长度单词)。

后端错误处理最佳实践

1. 封装通用查询辅助函数

把查询、结果校验的逻辑封装成复用函数,减少重复代码,统一错误处理:

async function executeSafeQuery(query, params, errorMessage = "Query failed") {
  try {
    const result = await excuteQuery(query, params);
    if (!result || result.length === 0) {
      throw new Error(`${errorMessage}: No results returned`);
    }
    return result;
  } catch (err) {
    console.error(`Database query error:`, err);
    throw new Error(`${errorMessage}: ${err.message}`);
  }
}

// 使用示例
const firstResult = await executeSafeQuery(q_1, [shape[0]], "Failed to get first word");
const word_1 = firstResult[0].word;

2. 限制重试次数

避免无限制递归,设置最大重试阈值,超过后抛出明确错误,便于监控和排查。

3. 详细日志记录

记录错误时包含查询参数、重试次数、错误栈等信息,方便定位问题根源。

4. 区分错误类型

自定义错误类,区分不同场景的错误(比如数据库连接错误、无结果错误、参数错误等),便于针对性处理:

class NoResultsError extends Error {
  constructor(message) {
    super(message);
    this.name = "NoResultsError";
  }
}

// 在getWord函数中抛出
if (!result || result.length === 0) {
  throw new NoResultsError(`No word found for params: ${JSON.stringify(params)}`);
}

5. 避免静默失败

不要在catch块中只打印日志而不处理错误,确保错误能被上层调用者捕获,或者触发告警机制。


内容的提问来源于stack exchange,提问作者Nikola Maksimovic

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 17:50:59