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

NodeJS与MySQL通信报错TypeError: cb is not a function 求助

解决Node.js MySQL接口的TypeError: cb is not a function错误

问题场景

前端通过fetch请求Node.js接口获取数据,接口与MySQL交互时抛出TypeError: cb is not a function错误,导致服务崩溃,需要修复确保接口稳定返回数据。

前端请求代码

function carregarsolicitacoes(){
fetch('/carregar-solicitacoes?usertag=' + localStorage.getItem('usertag'))
.then(response => response.json())
.then(data => {
  var select = document.getElementById('solic');
  data.forEach(solicitacao => {
    var option = document.createElement('option');
    option.text = solicitacao;
    select.add(option);
  });
  getarqproj();
})
.catch(error => {
  console.error('Erro ao carregar as solicitações:', error);
});
}

出错的Node.js接口代码

app.get('/carregar-solicitacoes', async function(req, res) {
  var solicitacoes = [];
  const usertag = req.query.usertag;

  try {
    const conn = await pool.getConnection();
    const result = await conn.query("SELECT projtag FROM notificacoes WHERE usertag = ?", [usertag]);
    
    const results = await Promise.all(result.map(row => {
      return conn.query("SELECT projetos.nome FROM projetos WHERE projtag = ?", [row.projtag]);
    }));

    results.forEach(result => {
      if (result.length > 0) {
        var linhasolicitacao = "Convite para o projeto " + result[0].nome;
        solicitacoes.push(linhasolicitacao);
      }
    });

    res.send(solicitacoes);
    conn.release();
  } catch (error) {
    res.status(500).send('Erro ao buscar as solicitações no banco de dados.');
  }
});

抛出的错误

/app/node_modules/mysql2/lib/pool.js:49
return process.nextTick(() => cb(null, connection));
^
TypeError: cb is not a function
at /app/node_modules/mysql2/lib/pool.js:49:37
at processTicksAndRejections (node:internal/process/task_queues:78:11)

正常工作的登录请求及接口参考

前端登录代码

function logar() {
    const xhr = new XMLHttpRequest();
    xhr.open('POST', '/fazer-login');
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.onload = function() {
      if (xhr.status === 200) {
        document.getElementById('quadrado').classList.add('sucesso');
        setTimeout(function() {
          document.getElementById('quadrado').classList.remove('sucesso');
          localStorage.setItem('islogged', 1);
          localStorage.setItem('usuario', document.getElementById('usu').value);
          localStorage.setItem('usertag', '');
          localStorage.setItem('nomeproj', '');
          localStorage.setItem('descproj', '');
          localStorage.setItem('projtag', '');
          localStorage.setItem('iscriador', '');
          location.replace("/index3.html");
        }, 1000);
      } else {
        document.getElementById('quadrado').classList.add('falha');
        setTimeout(function() {
          document.getElementById('quadrado').classList.remove('falha');
          window.alert('Erro ao logar, verifique as informações inseridas.');
        }, 1000);
      }
    };
    const dados = 'usu=' + encodeURIComponent(document.getElementById('usu').value) +
      '&sen=' + encodeURIComponent(document.getElementById('sen').value);
    xhr.send(dados);
  }

Node.js登录接口代码

app.post('/fazer-login', function (req, res) {
  const usu = req.body.usu;
  const sen = req.body.sen;

  pool.getConnection((err, conn) => {
    if (err) {
      console.error('Erro ao se conectar ao banco de dados:', err);
      res.status(500).send('Erro ao se conectar ao banco de dados.');
      return;
    }

    conn.query('SELECT * FROM contas WHERE nick = ? AND senha = ?', [usu, sen], (err, result) => {
      conn.release();

      if (err) {
        console.error('Erro ao realizar a consulta ao banco de dados:', err);
        res.status(500).send('Erro ao realizar a consulta ao banco de dados.');
        return;
      }

      if (result.length > 0) {
        usertag = result[0].nicktag;
        islogged = 1;
        usuario = usu;
        res.redirect('index3.html');
      } else {
        res.status(401).send('Usuário ou senha inválidos');
      }
    });
  });
});

错误原因及修复方案

错误原因

你使用的mysql2默认是回调风格API,直接用await调用pool.getConnection()会导致参数不匹配——它期望传入回调函数,但你没传,因此抛出cb is not a function错误。

修复方案

有两种可靠的修复方式:

方式1:改用回调风格(和登录接口保持一致)

把异步逻辑改成回调模式,和正常工作的登录接口写法统一:

app.get('/carregar-solicitacoes', function(req, res) {
  var solicitacoes = [];
  const usertag = req.query.usertag;

  pool.getConnection((err, conn) => {
    if (err) {
      console.error('Erro ao conectar ao banco:', err);
      return res.status(500).send('Erro ao buscar as solicitações no banco de dados.');
    }

    conn.query("SELECT projtag FROM notificacoes WHERE usertag = ?", [usertag], (err, result) => {
      if (err) {
        console.error('Erro na primeira consulta:', err);
        conn.release();
        return res.status(500).send('Erro ao buscar as solicitações no banco de dados.');
      }

      // 处理批量查询
      const queryPromises = result.map(row => {
        return new Promise((resolve, reject) => {
          conn.query("SELECT projetos.nome FROM projetos WHERE projtag = ?", [row.projtag], (err, projResult) => {
            if (err) reject(err);
            else resolve(projResult);
          });
        });
      });

      Promise.all(queryPromises)
        .then(results => {
          results.forEach(projResult => {
            if (projResult.length > 0) {
              solicitacoes.push(`Convite para o projeto ${projResult[0].nome}`);
            }
          });
          res.send(solicitacoes);
        })
        .catch(queryErr => {
          console.error('Erro na consulta de projetos:', queryErr);
          res.status(500).send('Erro ao buscar as solicitações no banco de dados.');
        })
        .finally(() => {
          conn.release(); // 无论成功失败都释放连接
        });
    });
  });
});

方式2:使用mysql2的Promise版本

如果想继续用async/await语法,需要切换到mysql2/promise模块,修改连接池初始化代码:

// 原回调版初始化
// const mysql = require('mysql2');
// const pool = mysql.createPool(...);

// 修改为Promise版初始化
const mysql = require('mysql2/promise');
const pool = mysql.createPool({
  // 你的数据库配置:host, user, password, database等
});

然后修改接口代码(保留async/await):

app.get('/carregar-solicitacoes', async function(req, res) {
  var solicitacoes = [];
  const usertag = req.query.usertag;
  let conn; // 提前声明连接变量,确保finally能访问

  try {
    conn = await pool.getConnection();
    const [result] = await conn.query("SELECT projtag FROM notificacoes WHERE usertag = ?", [usertag]);
    
    const results = await Promise.all(result.map(async row => {
      const [projResult] = await conn.query("SELECT projetos.nome FROM projetos WHERE projtag = ?", [row.projtag]);
      return projResult;
    }));

    results.forEach(projResult => {
      if (projResult.length > 0) {
        solicitacoes.push(`Convite para o projeto ${projResult[0].nome}`);
      }
    });

    res.send(solicitacoes);
  } catch (error) {
    console.error('Erro ao buscar solicitações:', error);
    res.status(500).send('Erro ao buscar as solicitações no banco de dados.');
  } finally {
    if (conn) conn.release(); // 确保连接被释放,避免内存泄漏
  }
});

额外优化建议

可以把两次查询合并为一次关联查询,减少数据库请求:

SELECT projetos.nome FROM notificacoes 
JOIN projetos ON notificacoes.projtag = projetos.projtag 
WHERE notificacoes.usertag = ?

这样只需要一次查询就能拿到所有需要的数据,性能更优。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 23:12:32