近日,遇到一事务问题,在执行create时报以下错误:
javascriptCopy code- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
Unhandled rejection SequelizeUniqueConstraintError: Validation error
at Query.formatError (/Users/fuyun/.../node_modules/sequelize/lib/dialects/mysql/query.js:223:16)
at Execute.handler [as onResult] (/Users/fuyun/.../node_modules/sequelize/lib/dialects/mysql/query.js:51:23)
at Execute.execute (/Users/fuyun/.../node_modules/mysql2/lib/commands/command.js:30:14)
at Connection.handlePacket (/Users/fuyun/.../node_modules/mysql2/lib/connection.js:417:32)
at PacketParser.onPacket (/Users/fuyun/.../node_modules/mysql2/lib/connection.js:75:12)
at PacketParser.executeStart (/Users/fuyun/.../node_modules/mysql2/lib/packet_parser.js:75:16)
at Socket.<anonymous> (/Users/fuyun/.../node_modules/mysql2/lib/connection.js:82:25)
at Socket.emit (events.js:223:5)
at Socket.EventEmitter.emit (domain.js:498:23)
at addChunk (_stream_readable.js:309:12)
at readableAddChunk (_stream_readable.js:290:11)
at Socket.Readable.push (_stream_readable.js:224:10)
at TCP.onStreamRead (internal/stream_base_commons.js:181:23)
Unhandled rejection SequelizeUniqueConstraintError: Validation error
at Query.formatError (/Users/fuyun/.../node_modules/sequelize/lib/dialects/mysql/query.js:223:16)
at Execute.handler [as onResult] (/Users/fuyun/.../node_modules/sequelize/lib/dialects/mysql/query.js:51:23)
at Execute.execute (/Users/fuyun/.../node_modules/mysql2/lib/commands/command.js:30:14)
at Connection.handlePacket (/Users/fuyun/.../node_modules/mysql2/lib/connection.js:417:32)
at PacketParser.onPacket (/Users/fuyun/.../node_modules/mysql2/lib/connection.js:75:12)
at PacketParser.executeStart (/Users/fuyun/.../node_modules/mysql2/lib/packet_parser.js:75:16)
at Socket. (/Users/fuyun/.../node_modules/mysql2/lib/connection.js:82:25)
at Socket.emit (events.js:223:5)
at Socket.EventEmitter.emit (domain.js:498:23)
at addChunk (_stream_readable.js:309:12)
at readableAddChunk (_stream_readable.js:290:11)
at Socket.Readable.push (_stream_readable.js:224:10)
at TCP.onStreamRead (internal/stream_base_commons.js:181:23)
查看日志后发现问题出在主键重复了,便引入异常处理,将error抛出,再通过reject返回给上层进行统一处理。但,此时又报另一个异常:
javascriptCopy code- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
Unhandled rejection Error: rollback has been called on this transaction(639ce933-3246-484d-9183-699093ee4cbd), you can no longer use it. (The rejected query is attached as the 'sql' property of this error)
at checkTransaction (/Users/fuyun/.../node_modules/sequelize/lib/sequelize.js:623:25)
at /Users/fuyun/.../node_modules/sequelize/lib/sequelize.js:636:9
at tryCatcher (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/util.js:16:23)
at Function.Promise.attempt.Promise.try (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/method.js:39:29)
at /Users/fuyun/.../node_modules/sequelize/lib/sequelize.js:631:53
at /Users/fuyun/.../node_modules/retry-as-promised/index.js:70:21
at new Promise (<anonymous>)
at retryAsPromised (/Users/fuyun/.../node_modules/retry-as-promised/index.js:60:10)
at /Users/fuyun/.../node_modules/sequelize/lib/sequelize.js:631:30
at tryCatcher (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/util.js:16:23)
at Function.Promise.attempt.Promise.try (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/method.js:39:29)
at Sequelize.query (/Users/fuyun/.../node_modules/sequelize/lib/sequelize.js:580:23)
at QueryInterface.insert (/Users/fuyun/.../node_modules/sequelize/lib/query-interface.js:885:27)
at /Users/fuyun/.../node_modules/sequelize/lib/model.js:3987:52
at bound (domain.js:419:14)
at runBound (domain.js:432:12)
at tryCatcher (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/promise.js:547:31)
at Promise._settlePromise (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/promise.js:604:18)
at Promise._settlePromise0 (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/promise.js:649:10)
at Promise._settlePromises (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/promise.js:729:18)
at _drainQueueStep (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/async.js:93:12)
at _drainQueue (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/async.js:86:9)
at Async._drainQueues (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/async.js:102:5)
at Immediate.Async.drainQueues [as _onImmediate] (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/async.js:15:14)
at processImmediate (internal/timers.js:439:21)
at process.topLevelDomainCallback (domain.js:130:23)
Unhandled rejection Error: rollback has been called on this transaction(639ce933-3246-484d-9183-699093ee4cbd), you can no longer use it. (The rejected query is attached as the 'sql' property of this error)
at checkTransaction (/Users/fuyun/.../node_modules/sequelize/lib/sequelize.js:623:25)
at /Users/fuyun/.../node_modules/sequelize/lib/sequelize.js:636:9
at tryCatcher (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/util.js:16:23)
at Function.Promise.attempt.Promise.try (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/method.js:39:29)
at /Users/fuyun/.../node_modules/sequelize/lib/sequelize.js:631:53
at /Users/fuyun/.../node_modules/retry-as-promised/index.js:70:21
at new Promise ()
at retryAsPromised (/Users/fuyun/.../node_modules/retry-as-promised/index.js:60:10)
at /Users/fuyun/.../node_modules/sequelize/lib/sequelize.js:631:30
at tryCatcher (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/util.js:16:23)
at Function.Promise.attempt.Promise.try (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/method.js:39:29)
at Sequelize.query (/Users/fuyun/.../node_modules/sequelize/lib/sequelize.js:580:23)
at QueryInterface.insert (/Users/fuyun/.../node_modules/sequelize/lib/query-interface.js:885:27)
at /Users/fuyun/.../node_modules/sequelize/lib/model.js:3987:52
at bound (domain.js:419:14)
at runBound (domain.js:432:12)
at tryCatcher (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/promise.js:547:31)
at Promise._settlePromise (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/promise.js:604:18)
at Promise._settlePromise0 (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/promise.js:649:10)
at Promise._settlePromises (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/promise.js:729:18)
at _drainQueueStep (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/async.js:93:12)
at _drainQueue (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/async.js:86:9)
at Async._drainQueues (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/async.js:102:5)
at Immediate.Async.drainQueues [as _onImmediate] (/Users/fuyun/.../node_modules/sequelize/node_modules/bluebird/js/release/async.js:15:14)
at processImmediate (internal/timers.js:439:21)
at process.topLevelDomainCallback (domain.js:130:23)
同时,还有一个warning:
javascriptCopy code- 1
(node:48615) [DEP0097] DeprecationWarning: Using a domain property in MakeCallback is deprecated. Use the async_context variant of MakeCallback or the AsyncResource class instead.
(node:48615) [DEP0097] DeprecationWarning: Using a domain property in MakeCallback is deprecated. Use the async_context variant of MakeCallback or the AsyncResource class instead.
网上搜了一圈,并没有找到解决方案,只找到一些关于Promise的异常处理的文章,于是试着加上try {...} catch {...}
,问题依旧。
而后将models.sequelize.transaction()
层的.then(onFulfill, onReject)
改为.then(onFulfill).catch(onError)
,依然无法解决。
甚至,因为关于domain的那个warning ,而琢磨是否domain的问题?于是又对照了一番node.js的官方API,发现除去deprecated的警告外,用法并没有错误。看来,问题还是出在Promise上。
又琢磨了半天,偶然发现model.create()
的结果处理中遗漏了reject和catch部分,于是分别在事务的几个子查询中都加上了异常处理逻辑。结果完美验证了所想。只是,虽然解决了error问题,但上面那个醒目的warning依然存在……
毫无头绪,既然都已经捕获了,也不再bubble了,结果也返回到页面了,为何还会出现warning?必然是在某个环节触发了domain机制。无解ing……
此问题也说明了,异步操作中的异常处理是何等复杂,如幽灵一般,难以捉摸……