我试图找出如何正确设置此代码块,以便提交函数将等待,直到插入所有行。目前我正在阅读一个csv,需要在每个表中插入一个新行。我还需要在父表中添加一行。在调用commit之前,我需要完成所有这些操作。我还没有掌握回调,所以请保持温和。
db.beginTransaction(function (err) {
if (err)
{
//could not begin a transaction for some reason.
logger.error("beginTransaction error: " +err);
}
//need to wrap this *************
db.query("INSERT INTO TABLE VALUES ('" + unique_id + "','real_time','" + msg + "',1,1,LOCALTIMESTAMP)", function(err){
if(err)
{
logger.error("error insert into parent table: "+err);
}
});
for(var i = 0; i < headers.length; i++)
{
//replaces single quote (') with two single quotes to escape it ('')
values[i] = values[i].replace("'","''");
db.query("INSERT INTO TABLE VALUES ('" + unique_id + "','" + headers[i] + "',0,'" + values[i] + "')", function(err){
if(err)
{
logger.error("error insert into child table: "+err);
}
});
}
//To here ************
db.commitTransaction(function (err) {
if (err)
{
//error during commit
logger.error("Commit error: "+err);
}
}); //end of commitTransaction
callback();
});//End of beginTransaction
答案 0 :(得分:1)
正如tadman所说,非手动转义值并使用参数化查询非常重要。请务必先修复此问题。
不幸的是,它看起来不像node-odbc
支持承诺。你可能能够使用像Bluebird.promisify这样的东西。目前您想要的是跟踪已完成的成功插入数量,然后在成功完成后提交事务。
let successfulInsertions = 0;
let insertionAttempts = 0;
for(var i = 0; i < headers.length; i++) {
db.query("INSERT INTO TABLE VALUES (?, ?, ?, ?)", params, err => {
if (err) {
logger.error("error insert into child table: "+err);
}
else {
successfulInsertions++;
}
insertionAttempts++;
if (insertionAttempts === headers.length) {
if (successfulInsertions === insertionAttempts) {
db.commitTransaction();
}
else {
db.rollbackTransaction();
}
callback();
}
});
}
有些库可以帮助解决这个问题,但它们需要重新编写代码。如果你可以在node-odbc库上使用Bluebird的promisifyAll,我会使用async / await重写它(这仍然是异步的并且功能相同):
await db.beginTransactionAsync();
try {
await db.queryAsync("INSERT INTO TABLE VALUES (?, ?, ?, ?)", params);
await Promise.all(headers.map((header, i) =>
db.queryAsync("INSERT INTO TABLE VALUES (?, ?, ?, ?)", [unique_id, header, 0, values[i])
);
await db.commitTransactionAsync();
} catch (err) {
logger.error(err);
db.rollbackTransaction();
}
请注意,如果beginTransaction
由于某种原因抛出错误,则此代码将引发错误。
答案 1 :(得分:1)
解决此同步问题有三种基本方法,我将在此处使用新样式arrow functions进行演示。传统的Node方式是回调:
a((err, resultA) => {
// Fires when A is done or errored out
if (err) {
// Log, panic, etc.
return;
}
b((err, resultB) => {
// Fires when A and B are done or A is done and B errored out
if (err) {
// Log, panic, etc.
return;
}
c((err, resultC) => {
// Fires when A, B and C are done or A and B are done and C errored out
if (err) {
// Log, panic, etc.
return;
}
});
});
});
这就是人们所说的&#34;回调地狱&#34;因为嵌入和错误传播代码变得越来越荒谬,因为依赖关系变得越来越复杂。我发现这种风格对于任何非平凡的应用都是不可持续的。
下一个风格是Promise驱动:
a().then(resultA => {
// Fires when A is done
return b();
}).then(resultB => {
// Fires when B is done
return c();
}).then(resultC => {
// Fires when C is done
}).catch(err => {
// Fires if any of the previous calls produce an error
});
这往往很多&#34;更平坦&#34;并且更容易理解,但对于应该简单的事情,它仍然有很多重要的语法。较新的async / await样式基于promises构建,通过在JavaScript语法中添加对它们的支持:
try {
let resultA = await a();
let resultB = await a();
let resultC = await a();
} catch(err) {
// Fires when any error occurs
}
这适用于任何标记为async
的函数,如:
async function runQueries() {
// async code
}
这可以让您的生活更轻松。您还可以使用传统的try
/ catch
表示法来处理错误,并相应地进行传播。
答案 2 :(得分:0)
我真的不了解您的代码,如果出现错误,为什么不返回或停止代码?
例如,您应该拥有这样的代码
db.beginTransaction(function (err) {
if (err)
return logger.error("beginTransaction error: " +err), db.rollback(/*...*/)
//....
}
其次,您应该使用async/await
语法更改整个代码。
async function foo () {
await new Promise((next, err)=> {
db.beginTransaction(e => e ? err(e) : next())
})
await new Promise((next, err)=> {
db.query(`INSERT INTO TABLE VALUES ('${unique_id}','real_time','${msg}',1,1,LOCALTIMESTAMP)`, e => e ? err(e) : next())
})
for (var i = 0; i < headers.length; i++) {
await new Promise((next, err)=> {
db.query(`INSERT INTO TABLE VALUES ('${unique_id}','${headers[i]}',0,'${values[i]}')`, e => e ? err(e) : next())
})
}
await new Promise((next, err)=> {
db.commitTransaction(e => e ? err(e) : next())
})
}
foo()
.then(()=> callback())
.catch(e=> logger.error(`Error: ${e}`))