我想在完成事务之前在事务中并行执行插入。我使用了 Promise.all() 和 bluebird promises 如果一个失败了就取消所有的promise。问题是承诺似乎在插入实际执行之前就结束了。我正在使用 Knex.js。我有 2 个承诺,一个在 users 表中插入用户的用户名和电子邮件,另一个是加密用户密码并将电子邮件和加密密码插入登录表中。
我找到了执行承诺和插入的顺序。他们以这种方式执行。(插入用户名和电子邮件的承诺得到解决)->(Knex 调试器说运行了用户名和电子邮件的插入命令)->(承诺比插入电子邮件和密码得到解决)->(transaction.commit)->(Knex调试器表示已运行电子邮件和密码的插入命令,但事务已结束并引发错误)。这里的问题显然是在执行电子邮件和密码插入之前执行了电子邮件和密码承诺。
const addUser = (username, email, password) => {
return db.transaction(trx => {
let addLoginEntry = Promise.resolve(bcrypt.hash(password, 10)
.then(secret => {
trx("login").insert({
email: email,
secret: secret
}).then(console.log("PASSWORD INSERTED"));
})
);
let addUserEntry = Promise.resolve(
trx("users").insert({
username: username,
email: email
})
.then(console.log("USER INFO INSERTED"))
)
Promise.all([
addLoginEntry,
addUserEntry
])
.then(args => {
console.log("All promises done");
trx.commit(args);
})
.catch(error => {
[addLoginEntry, addUserEntry].forEach(promise =>promise.cancel());
console.log(error);
trx.rollback();
});
});
}
我希望登录表和用户表都被更新,但由于事务提交发生在登录更新被添加到事务之前,因此只更新了用户表。以下是我在 Knex 中使用 debug=true 运行程序时收到的错误消息:
USER INFO INSERTED
{ method: 'insert',
options: {},
timeout: false,
cancelOnTimeout: false,
bindings: [ 'testemail@test.com', 'test' ],
__knexQueryUid: '2b1d59b1-1246-4237-87f1-d3fbfff7ba80',
sql: 'insert into "users" ("email", "username") values (?, ?)',
returning: undefined }
PASSWORD INSERTED
All promises done
{ method: 'insert',
options: {},
timeout: false,
cancelOnTimeout: false,
bindings:
[ 'testemail@test.com',
'$2b$10$D.qlOo7aDv4WCzssXGXuQeXQ3lZwWZ1.b1CRIn4DuSD.6ov.jzhBm' ],
__knexQueryUid: 'e3afdc4a-53bd-4f0d-ad71-7aab0d92d014',
sql: 'insert into "login" ("email", "secret") values (?, ?)',
returning: undefined }
Unhandled rejection Error: Transaction query already complete, run with DEBUG=knex:tx for more info
at completedError (C:\PATH_TO\node_modules\knex\src\transaction.js:338:9)
at C:\PATH_TO\node_modules\knex\src\transaction.js:304:24
at Promise.cancellationExecute [as _execute] (C:\PATH_TO\node_modules\bluebird\js\release\debuggability.js:335:9)
at Promise._resolveFromExecutor (C:\PATH_TO\node_modules\bluebird\js\release\promise.js:488:18)
at new Promise (C:\PATH_TO\node_modules\bluebird\js\release\promise.js:79:10)
at Client_PG.trxClient.query (C:\PATH_TO\node_modules\knex\src\transaction.js:300:12)
at Runner.query (C:\PATH_TO\node_modules\knex\src\runner.js:136:36)
at C:\PATH_TO\node_modules\knex\src\runner.js:40:23
at tryCatcher (C:\PATH_TO\node_modules\bluebird\js\release\util.js:16:23)
at C:\PATH_TO\node_modules\bluebird\js\release\using.js:185:26
at tryCatcher (C:\PATH_TO\node_modules\bluebird\js\release\util.js:16:23)
at Promise._settlePromiseFromHandler (C:\PATH_TO\node_modules\bluebird\js\release\promise.js:517:31)
at Promise._settlePromise (C:\PATH_TO\node_modules\bluebird\js\release\promise.js:574:18)
at Promise._settlePromise0 (C:\PATH_TO\node_modules\bluebird\js\release\promise.js:619:10)
at Promise._settlePromises (C:\PATH_TO\node_modules\bluebird\js\release\promise.js:699:18)
at Promise._fulfill (C:\PATH_TO\node_modules\bluebird\js\release\promise.js:643:18)