Express调用save方法报Cannot read property 'then' of undefined问题排查
报错原因及解决方案
报错产生原因
- 自定义save方法未返回Promise对象:你写的save方法执行完数据库操作的链式调用后没有返回整个Promise链,导致
car.save()执行后返回值为undefined,调用undefined的then方法自然会触发该报错。 - db变量作用域错误:你在第一个
then中拿到的数据库连接对象仅在当前then的作用域内有效,后续then直接调用db会抛出未定义错误,就算解决了返回值问题也会导致事务执行失败。 - 异步操作未返回Promise:链式调用中所有的
db.query都是异步操作,你没有返回它们的执行结果(mysql2的query方法默认返回Promise),会导致事务执行顺序错乱,无法按预期完成多表插入。
修复方案
修改后的save方法代码如下:
save() { // 返回整个Promise链,供外部调用.then/.catch return db.getConnection() .then((dbConn) => { // 将连接对象存在当前作用域,后续所有操作复用该连接 return dbConn.query('START TRANSACTION') .then(() => { return dbConn.query('INSERT INTO cars (model_year, make, model, color, miles, transmission, layout, engine_type) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [this.model_year, this.make, this.model, this.color,this.miles, this.transmission, this.layout, this.engine_type]) }) .then(() => { return dbConn.query('INSERT INTO car_photos (car_photo_url) VALUES (?)', [this.car_photo_url]) }) .then(() => { return dbConn.query('INSERT INTO car_price (car_price) VALUES (?)', [this.car_price]) }) .then(() => { return dbConn.query('INSERT INTO sales_status (sale_status, for_sale) VALUES (?, ?)', [this.sale_status, this.for_sale]) }) .then(() => { return dbConn.query('COMMIT'); }) .catch((error) => { // 出错时回滚事务,同时把错误抛出给外部捕获 return dbConn.query('ROLLBACK').then(() => { throw error }); }) .finally(() => { // 操作结束后释放连接,避免连接泄露 dbConn.release() }) }) }
修改点说明:
- 给整个Promise链式调用添加return,让save方法返回标准Promise对象,外部可正常调用
then/catch - 修正了数据库连接的作用域问题,所有事务操作复用同一个连接
- 每个异步query操作都添加return,保证事务按顺序执行
- 新增finally块释放连接,避免数据库连接被占满无法处理新请求
- 回滚操作后重新抛出错误,控制器层的catch可以拿到具体报错信息做后续处理
内容的提问来源于stack exchange,提问作者DeltaFlyer
相关产品推荐
相关产品推荐

