Node.js中mysql查询错误无法被try/catch捕获致崩溃问题
问题根因
你写的外层try/catch完全抓不到回调里抛出的错误,本质是Node.js异步执行的时序问题:
connection.query是典型的异步回调风格API,调用后不会阻塞等待数据库返回结果,会立刻把传入的回调函数注册到事件队列,外层的try/catch块会在回调实际执行前就运行完毕、退出上下文- 等数据库返回错误、回调内部执行
throw error的时候,外层包裹的try/catch早就结束运行了,这个抛出的错误会成为未捕获的全局异常,直接砸穿整个事件循环把进程打崩,自然就出现你看到的崩溃日志 - 顺带提一句,你原来成功分支的写法也有问题:
response.send()调用后响应就已经发出去了,后面再写response.status(200)根本不会生效,状态码必须在send之前设置
修复方案
方案1:直接在回调内处理错误(最小改动)
不要在回调里往外抛错,直接在回调的错误分支里处理响应逻辑即可,改完代码如下:
connection.query(queryFromClient, function (error, result, field) { if (error) { console.log("Query error from client"); return response.status(422).send("Query error"); } response.status(200).send(result[0]); });
这里加return是为了阻断错误分支执行完后,继续往下跑成功分支的逻辑。
方案2:改Promise+async/await写法(适配try/catch习惯)
如果你更习惯用try/catch统一捕获错误的写法,可以把回调风格的query包装成Promise,配合async路由使用,这时候try/catch就能正常捕获错误了:
// 先把mysql查询包装成Promise function runQuery(sql) { return new Promise((resolve, reject) => { connection.query(sql, (err, results, fields) => { if (err) return reject(err); resolve({ results, fields }); }) }) } // 路由函数声明为async app.get('/your-query-path', async (request, response) => { try { const { results } = await runQuery(queryFromClient); response.status(200).send(results[0]); } catch (error) { console.log("Query error from client"); response.status(422).send("Query error"); } })
额外提醒:直接接收客户端传入的SQL语句执行有极高的SQL注入风险,生产环境绝对不能这么写,一定要做参数校验和权限控制。
内容的提问来源于stack exchange,提问作者user3542843
相关产品推荐
相关产品推荐

