Reputation: 3987
I created a node.js application that uses the knex library to make database operations. The database is Microsoft SQL Server. I created a script called db.js that returns the knex object, and i have a controller.js script that makes the actually needed database operations. I have all the operations wrapped inside a translation statement, which brings me to my question. What i would like to do, is pass in a parameter that tells the transaction to rollback or commit. However, whenever i try to pass this function in, it just fails. Does anyone know if this feature achievable ? I was able to do this feature with the catch function.
I don't think its db specific, so anyone can download knex, hook it up a db and give it a shot with the code below.
example.js
/**
* @param {userID} Int
* @param {rollback} Boolean
*/
const getUsers = (userID, rollback) => {
// Using tran as a transaction object:
return db('master').transaction((tran) => {
db('master')
.select()
.from('users')
.where({ 'user_id': userID })
.transacting(tran)
.then(tran.rollback) // Works
// .then(transact(tran, rollback)) throws error
.catch((error) => {
logError(error, tran); // Works
});
// .catch(tran.rollback);
});
};
const logError = (error, transaction) => {
transaction.rollback;
console.log('transaction error: ',error);
console.log('transaction log: ',transaction);
};
const transact = (transaction, rollback) => {
try {
if (rollback) return transaction.rollback;
else return transaction.commit;
} catch (error) {
console.log(error);
}
};
const user = await getUsers(1, true); // error is thrown
assert.strictEqual(user.constructor === Array, true);
assert.strictEqual(user.length == 0, true);
Error Message
Error: the array [ {
"user_id": 1
"user_name": "JonnyBoy"
"zip": 1200
"email": "[email protected]"
} ] was thrown, throw an Error :)
Upvotes: 0
Views: 1154
Reputation: 84687
then
takes a function as its first parameter. If the Promise resolves, the function that's passed to then
is called with the value the Promise resolved to. The rollback
property on the transaction object is a function so you can write:
someQuery().then(trans.rollback)
and rollback
will be called when someQuery
resolves. You could also write:
someQuery.then(result => trans.rollback(result))
These statements are equivalent.
That said, minimally, there's two changes that you need to make. One, fix how you're calling transact
. For example:
.then(() => transact(tran, rollback))
And change how transact
calls rollback
:
const transact = (trx, rollback) => {
const action = rollback ? trx.rollback : trx.commit
return action()
}
Also bear in mind that rollback
itself will return a rejected Promise with a generic error. You can pass a custom error to rollback
and it will reject with that error instead.
Upvotes: 1