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
相关产品推荐
相关产品推荐

