Node.js执行MySQL查询时使用Try/Catch是否属于冗余操作?
问题解答
你当前的写法中,包裹con.query的try/catch属于完全冗余的操作,根本无法捕获到SQL执行抛出的错误,也达不到避免服务崩溃的效果。
核心原因是你使用的是mysql库的回调式异步API:try/catch只能捕获当前执行上下文内的同步错误,以及async/await语法下的异步错误。回调函数是在query操作完成后才被事件循环调用执行的,此时外层的try/catch上下文已经执行结束,你在回调内部throw err的操作没有外层作用域可以捕获,最终还是会导致进程抛出未捕获异常崩溃。
方案1:沿用回调模式,去掉外层try/catch
直接在回调的错误分支处理异常即可,不需要throw错误,示例代码:
var con = mysql.createConnection({ host: 'mysql1', user: 'root', database: 'assignment', password: 'admin' }); // 注意:原有直接拼接SQL的写法存在SQL注入风险,必须改用参数化查询 let sqlQuery = `INSERT INTO CBOdb (staffName, staffID, staffPassword, time) VALUES (?, ?, ?, NOW())`; con.query(sqlQuery, [staffName, staffID, staffPassword], function(err, result) { if (err) { // 此处直接处理错误逻辑即可,无需抛出 console.error('员工注册失败:', err); res.send(1); return; } res.send(0); })
方案2:改用async/await语法,搭配try/catch捕获错误
如果想要使用try/catch的写法,需要先将回调式的query方法封装为Promise,再用async/await调用,此时try/catch才能正常捕获异步错误:
var con = mysql.createConnection({ host: 'mysql1', user: 'root', database: 'assignment', password: 'admin' }); // 封装query为Promise形式,也可以直接使用mysql2的promise版API const util = require('util'); const query = util.promisify(con.query).bind(con); let sqlQuery = `INSERT INTO CBOdb (staffName, staffID, staffPassword, time) VALUES (?, ?, ?, NOW())`; // 异步函数内用await调用,try/catch捕获错误 (async () => { try { await query(sqlQuery, [staffName, staffID, staffPassword]); res.send(0); } catch (err) { console.error('员工注册失败:', err); res.send(1); } })();
额外安全提示
你原有代码中直接用模板字符串拼接用户输入生成SQL的写法存在严重的SQL注入漏洞,攻击者可以通过构造特殊的员工姓名、ID等参数窃取、篡改甚至删除整个数据库的数据,必须改为上面示例中的参数化查询写法,将用户输入作为参数传入query方法,由库底层做转义处理。
内容的提问来源于stack exchange,提问作者ConnerWithAnE
相关产品推荐
相关产品推荐

