问题描述
我是node.js的新手,在连接到mssql
数据库并准备/执行准备好的语句时遇到问题。
我有以下代码:
this.connectionPool.connect().then(pool => {
// Create prepared statement
stmt = new mssql.PreparedStatement(pool);
// PREPARE
stmt.prepare(command,err => {
//TODO: check for errors in prepare
// EXECUTE
stmt.execute((err,result) => {
//TODO: check for errors in execute
// UNPREPARE
stmt.unprepare(err => {
//TODO: check for errors in unprepare
});
console.log(`Rows affected: ${stmt.rowsAffected}`);
console.log(`Result: ${result}`);
return result;
});
});
}).catch(err => {
console.log(`Connection pool error: ${err}`);
}).finally(() => {
// Close connection
console.log("Closing connection.");
if (this.connectionPool.connected) {
this.connectionPool.close();
}
});
我发现finally()
诺言与then()
同时执行,这是我不期望的。这将导致在准备语句之前关闭连接。
ConnectionError: connection is closed
如何确保仅在语句执行后 关闭连接?
解决方法
回调是异步执行的,因此您需要在承诺链中添加execute
的结果:
this.connectionPool.connect().then(pool => {
// Create prepared statement
stmt = new mssql.PreparedStatement(pool)
// return a promise to add it to the promise chain
return new Promise((resolve,reject) => {
stmt.prepare(command,err => {
// TODO: check for errors in prepare
if (err) {
reject(err)
return
}
// EXECUTE
stmt.execute((err,result) => {
// TODO: check for errors in execute
if (err) {
reject(err)
return
}
// UNPREPARE
stmt.unprepare(err => {
// TODO: check for errors in unprepare
if (err) {
reject(err)
}
})
console.log(`Rows affected: ${stmt.rowsAffected}`)
console.log(`Result: ${result}`)
resolve(result)
})
})
})
}).catch(err => {
console.log(`Connection pool error: ${err}`)
}).finally(() => {
// Close connection
console.log('Closing connection.')
if (this.connectionPool.connected) {
this.connectionPool.close()
}
})
如果开箱即用stmt.prepare
支持承诺,您可以不将其包装在new Promise
中将其返回
所有承诺版本:
this.connectionPool.connect().then(pool => {
// Create prepared statement
stmt = new mssql.PreparedStatement(pool)
return stmt.prepare(command)
.then(() => stmt.execute())
.then((result) => {
console.log(`Rows affected: ${stmt.rowsAffected}`)
console.log(`Result: ${result}`)
})
.finally(() => stmt.unprepare())
}).catch(err => {
console.log(`Connection pool error: ${err}`)
}).finally(() => {
// Close connection
console.log('Closing connection.')
if (this.connectionPool.connected) {
this.connectionPool.close()
}
})
,
.prepare()
,.execute()
和.unprepare()
方法都接受回调。除非这些方法被“承诺化”,否则this.connectionPool.connect().then().catch().finally()
链无法得知准备-执行-未准备过程的结果。
准备-执行-取消准备过程可以如下进行承诺:
this.connectionPool.connect()
.then(pool => {
let stmt = new mssql.PreparedStatement(pool);
return new Promise((resolve,reject) => {
stmt.prepare(command,err => {
if(err) {
reject(err);
} else {
stmt.execute((err,result) => {
if(err) {
reject(err);
} else {
stmt.unprepare(err => {
if(err) {
reject(err);
} else {
resolve(result);
}
});
}
});
}
});
});
})
.catch(err => {
console.log(`Prepared statement error: ${err.message}`);
})
.finally(() => {
if (this.connectionPool.connected) {
this.connectionPool.close();
}
});
现在,catch()
和finally()
块将按您期望的顺序排序。