如何使用异步模块在nodejs中实现回滚?
问题描述:
自从最近2个月以来,我一直在使用nodejs,这是我在处理异步模块时遇到的问题。有时候,在某些错误异步错误异步从这个tasks.Consider代码的中间调用错误:如何使用异步模块在nodejs中实现回滚?
var mysql = require('mysql');
var async = require('async');
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
database: 'test',
password: '12345'
});
var chairArr = ['Red', 'Green', 'Yellow', 'Voilet', 'Brown'];
var inventoryName = "Chairs";
addInventory(inventoryName, chairArr, function(err, result) {
if(err) {
console.log("Err : "+err);
}
console.log("Successfully added an inventory");
});
function addInventory(inventoryName, chairArr, callback) {
var sqlQuery = "INSERT INTO tb_inventory(name, added_on) VALUES(?, NOW())";
connection.query(sqlQuery, [inventoryName], function(err, result) {
if(err) {
return callback(err, null);
}
var inventoryId = result.insertId;
var tasks = [];
for(var i = 0; i < chairArr.length; i++) {
tasks.push(addChair.bind(null, inventoryId, chairArr[i]));
}
async.parallel(tasks, function(taskErr, taskRes) {
if(taskErr) {
return callback(taskErr, null);
}
callback(null, result);
});
});
}
function addChair(inventoryId, chairColor, callback) {
var sqlQuery = "INSERT INTO tb_chairs(inventory_id, color) VALUES(?, ?)";
connection.query(sqlQuery, [inventoryId, chairColor], function(err, result) {
if(err) {
return callback(err, null);
}
callback(null, result);
});
}
这个简单的程序只是插入到两个表tb_inventory和tb_chairs。我的问题是:有时由于来自前端的参数或我的错误查询不会执行,而异步并行调用从该错误回调。有没有办法回滚(即删除表中的所有插入的条目)。谁能告诉我如何在错误回调中实现它(即跟踪所有的ID插入和删除?)。我们可以在全球使用mysql transactions
吗?
答
每当使用一系列函数时,我们都可以从池中获取本地连接,并在异步调用期间调用的函数中传递该本地连接。可以在异步调用的回调中处理提交或回滚。
var mysql = require('mysql');
var async = require('async');
var dbPool = mysql.createPool({
host: 'localhost',
user: 'root',
database: 'test',
password: '12345',
connectionLimit: 10
});
//var chairArr = ['Red', 'Green!++++++++++++++++!!!!!!!!!!!!!!!!!!!!!!!!!!!!', 'Yellow', 'Voilet', 'Brown']; //Case where query fails due to VARCHAR(20) limit
var chairArr = ['Red', 'Green', 'Yellow', 'Voilet', 'Brown'];
var inventoryName = "SOME ITEM ";
dbPool.getConnection(function(conErr, localConnection) {
localConnection.beginTransaction(function(transactionErr) {
if(transactionErr) {
console.log("There was some error in begining transaction");
return;
}
addInventory(localConnection, inventoryName, chairArr, function(err, result) {
if(err) {
console.log("Err : "+err);
return;
}
else {
console.log("Successfully added an inventory");
}
});
});
});
function addInventory(localConnection, inventoryName, chairArr, callback) {
var sqlQuery = "INSERT INTO tb_inventory(name, added_on) VALUES(?, NOW())";
localConnection.query(sqlQuery, [inventoryName], function(err, result) {
if(err) {
return callback(err, null);
}
var inventoryId = result.insertId;
var tasks = [];
for(var i = 0; i < chairArr.length; i++) {
tasks.push(addChair.bind(null, localConnection, inventoryId, chairArr[i]));
}
async.parallel(tasks, function(err, asyncRes) {
if(err) {
rollback(localConnection, function(rollErr, rollRes) {
return callback(err, null);
});
}
else {
localConnection.commit(function(commitErr, commitRes) {
console.log("transaction succeded");
return callback(null, "Success");
});
}
});
});
}
function addChair(localConnection, inventoryId, chairColor, callback) {
var sqlQuery = "INSERT INTO tb_chairs(inventory_id, color) VALUES(?, ?)";
localConnection.query(sqlQuery, [inventoryId, chairColor], function(err, result) {
if(err) {
return callback(err, null);
}
callback(null, result);
});
}
function rollback(localConnection, callback) {
localConnection.rollback(function(err, result) {
if(err) {
console.log("ROLLBACK Failed");
return callback(err, null);
}
console.log("ROLLBACK successful!");
callback(null, result);
});
}
我希望它有帮助。
你读过[this](https://www.npmjs.com/package/mysql#transactions)吗? – robertklep
是的,connection.beginTransaction需要一系列查询。但我不知道我将如何实现一系列函数调用之间的事务,这可能涉及或可能不涉及查询数据库。我想知道是否有某种方式来实现失败时的回滚机制。 –