Knex 交易承诺警告
Knex transaction Promises warnings
我在使用 Knex、事务和 Promises 时遇到了困难,希望得到 SO 专家的帮助 :)
通过阅读类似的帖子和很多关于 Promises 的文章,我明白我离解决方案不远了,但发现下面的代码对于这样一个简单的任务来说真的过于复杂了。
这个 class 只是公开了一个函数,该函数接收先前构建的查询并且需要在首次调用 "load_user_settings" 函数后 运行 它(使用 PostgreSQL 9.5 作为数据库) .我实际上需要第二个查询的结果(或错误),所以简单地将 trx.commit 放在 "then" 中对我不起作用。
我的函数末尾的 process.nextTick 真的感觉像是一个巨大的 hack,添加它是为了避免将我的整个应用程序更改为 Promises,因为目前这是不可行的。如果没有它,我经常会发现自己收到 Promise 警告 ("Unhandled rejection Error") 并在我的代码稍后抛出异常时挂起代码。
此外,我有时会在日志中看到以下警告:
警告:承诺因非错误而被拒绝:[对象未定义]
我猜那个警告与这个问题有某种关系...
如果可以找到仅使用回调的解决方案,那也很好,因为我们的整个应用程序当前都在使用回调。
const pg = require('pg');
const async = require('async');
class MyClass {
constructor(connectionInfo) {
this.connectionInfo = connectionInfo; // This is an object containing user, password, database, host and port.
this.pgKnex = require('knex')({
client : 'pg',
connection : this.connectionInfo,
pool : {
min : 1,
max : 25
}
});
}
query(username, sql, params, callback) {
let response;
let error;
this.pgKnex.transaction((trx) => {
return this.pgKnex.raw(`SELECT load_user_settings(?)`, [username]).transacting(trx)
.then(() => {
return this.pgKnex.raw(sql, params).transacting(trx);
})
.then((result) => {
response = result;
return trx.commit();
}).catch((err) => {
error = err;
console.error(err);
return trx.rollback();
});
}).catch((err) => {
error = err;
console.error(err);
}).then(() => {
process.nextTick(() => {
callback(error, response);
});
});
}
}
module.exports = MyClass;
根据 Bergi 的评论,我编写了这个版本,它避免了任何黑客攻击并删除了我收到的所有承诺警告:
query(username, sql, params, callback) {
this.pgKnex.transaction((trx) => {
this.pgKnex.raw(`SELECT set_config('ims.username', ?, false)`, [username]).transacting(trx).asCallback((err, result) => {
if(err) {
trx.rollback().asCallback(() => {
console.error(err);
callback(err);
});
return;
}
this.pgKnex.raw(sql, params).transacting(trx).asCallback((err, result) => {
if(err) {
trx.rollback().asCallback(() => {
console.error(err);
callback(err);
});
return;
}
trx.commit().asCallback((commitErr) => {
callback(commitErr, result);
});
});
});
}).asCallback((err, result) => {
// Nothing to do here ... I guess?
});
}
但我仍然觉得我可以改进...
让我试着简化一下:
query(username, sql, params, callback) {
this.pgKnex.transaction((trx) => {
return this.pgKnex.raw(`SELECT set_config('ims.username', ?, false)`, [username])
.transacting(trx)
.then(() => {
return this.pgKnex.raw(sql, params)
.transacting(trx);
});
}).asCallback(callback);
}
当使用交易块时,您可以 return 一个 Promise
如果 Promise
是 resolved/rejected,knex 将自动 commit/rollback。
最后的 asCallback(callback)
调用确保承诺链中抛出的错误将传递给 callback
。您不需要单独处理每个承诺的错误,因为承诺链的所有错误都会冒泡。同样,如果结果是 return 来自第二个 sql 查询(承诺链的最后一个),则此结果作为第二个参数传递给 callback
.
我在使用 Knex、事务和 Promises 时遇到了困难,希望得到 SO 专家的帮助 :)
通过阅读类似的帖子和很多关于 Promises 的文章,我明白我离解决方案不远了,但发现下面的代码对于这样一个简单的任务来说真的过于复杂了。
这个 class 只是公开了一个函数,该函数接收先前构建的查询并且需要在首次调用 "load_user_settings" 函数后 运行 它(使用 PostgreSQL 9.5 作为数据库) .我实际上需要第二个查询的结果(或错误),所以简单地将 trx.commit 放在 "then" 中对我不起作用。
我的函数末尾的 process.nextTick 真的感觉像是一个巨大的 hack,添加它是为了避免将我的整个应用程序更改为 Promises,因为目前这是不可行的。如果没有它,我经常会发现自己收到 Promise 警告 ("Unhandled rejection Error") 并在我的代码稍后抛出异常时挂起代码。
此外,我有时会在日志中看到以下警告: 警告:承诺因非错误而被拒绝:[对象未定义] 我猜那个警告与这个问题有某种关系...
如果可以找到仅使用回调的解决方案,那也很好,因为我们的整个应用程序当前都在使用回调。
const pg = require('pg');
const async = require('async');
class MyClass {
constructor(connectionInfo) {
this.connectionInfo = connectionInfo; // This is an object containing user, password, database, host and port.
this.pgKnex = require('knex')({
client : 'pg',
connection : this.connectionInfo,
pool : {
min : 1,
max : 25
}
});
}
query(username, sql, params, callback) {
let response;
let error;
this.pgKnex.transaction((trx) => {
return this.pgKnex.raw(`SELECT load_user_settings(?)`, [username]).transacting(trx)
.then(() => {
return this.pgKnex.raw(sql, params).transacting(trx);
})
.then((result) => {
response = result;
return trx.commit();
}).catch((err) => {
error = err;
console.error(err);
return trx.rollback();
});
}).catch((err) => {
error = err;
console.error(err);
}).then(() => {
process.nextTick(() => {
callback(error, response);
});
});
}
}
module.exports = MyClass;
根据 Bergi 的评论,我编写了这个版本,它避免了任何黑客攻击并删除了我收到的所有承诺警告:
query(username, sql, params, callback) {
this.pgKnex.transaction((trx) => {
this.pgKnex.raw(`SELECT set_config('ims.username', ?, false)`, [username]).transacting(trx).asCallback((err, result) => {
if(err) {
trx.rollback().asCallback(() => {
console.error(err);
callback(err);
});
return;
}
this.pgKnex.raw(sql, params).transacting(trx).asCallback((err, result) => {
if(err) {
trx.rollback().asCallback(() => {
console.error(err);
callback(err);
});
return;
}
trx.commit().asCallback((commitErr) => {
callback(commitErr, result);
});
});
});
}).asCallback((err, result) => {
// Nothing to do here ... I guess?
});
}
但我仍然觉得我可以改进...
让我试着简化一下:
query(username, sql, params, callback) {
this.pgKnex.transaction((trx) => {
return this.pgKnex.raw(`SELECT set_config('ims.username', ?, false)`, [username])
.transacting(trx)
.then(() => {
return this.pgKnex.raw(sql, params)
.transacting(trx);
});
}).asCallback(callback);
}
当使用交易块时,您可以 return 一个 Promise
如果 Promise
是 resolved/rejected,knex 将自动 commit/rollback。
最后的 asCallback(callback)
调用确保承诺链中抛出的错误将传递给 callback
。您不需要单独处理每个承诺的错误,因为承诺链的所有错误都会冒泡。同样,如果结果是 return 来自第二个 sql 查询(承诺链的最后一个),则此结果作为第二个参数传递给 callback
.