我正在撞击这个图书馆。我试图设置一个单例中间类,它将启动连接,然后通过静态方法共享该连接。我的问题是我在设置事物时遇到困难,以至于在运行查询时连接已经打开,但无需再次重新打开。由于连接的打开当然是异步的,我不能只把所有内容都放在开始回调中,因为这在其他时间完全发生在其他地方......我唯一能做的就是分享mssql.Connection
,是"connecting": true
。这就是我不在connection.connect()
Database.connect()
的原因
如何知道连接已打开,如何打开连接并继续准备语句并运行查询?
我的问题是,无论何时我的代码第二次到达connection.connect()
,都会遇到错误 EALREADYCONNECTING
,因为连接已经打开。
我想过做一些Promise查询池,一旦连接本身通过Promise得到解决,但是现在我的脑子很困惑!
let mssql = require('mssql');
let fs = require('fs');
class Database
{
static connect(username, password, server, database)
{
if (Database.connection !== null) {
return Database.connection;
}
let storedUsername = null;
let storedPassword = null;
let storedServer = null;
let storedDatabase = null;
try {
fs.accessSync(__dirname + '/../../config.json');
let data = fs.readFileSync(__dirname + '/../../config.json')
data = JSON.parse(data);
storedUsername = data.sql.username;
storedPassword = data.sql.password;
storedServer = data.sql.server;
storedDatabase = data.sql.database;
} catch (e) {
// Do nothing
}
var config = {
user: username || storedUsername || '',
password: password || storedPassword || '',
server: server || storedServer || 'localhost',
database: database || storedDatabase || '',
}
Database.connection = new mssql.Connection(config);
return Database.connection;
}
static getConnection()
{
if (Database.connection === null) {
try {
Database.connect();
} catch (e) {
throw new Error('Database.getConnection: Database not connected.');
}
}
return Database.connection;
}
static getInstance()
{
return mssql;
}
static query(query, fields)
{
if (typeof query !== 'string' || typeof fields !== 'object') {
throw new Error("Invalid parameters");
}
let db = Database.getInstance();
let connection = Database.getConnection();
let ps = new db.PreparedStatement(connection);
let values = {};
fields.forEach(function(current, index) {
ps.input(current.name, current.type);
values[current.name] = current.value;
});
connection.connect(function(err) {
if (err) {
throw err;
}
ps.prepare(query, function(err) {
if (err) {
throw new Error(err);
}
ps.execute(values, function(err, recordset, affected) {
if (err) {
ps.unprepare(function(err) {
if (err) {
throw new Error(err);
}
});
throw new Error(err);
}
ps.unprepare(function(err) {
if (err) {
throw new Error(err);
}
});
});
});
});
}
}
Database.connection = null;
module.exports = Database;
答案 0 :(得分:1)
不完全确定你所遵循的模式是否对node.js有用,它对于非事件驱动的编程非常有用,但是要使它与node.js一起使用,你需要按照注释中的建议进行循环。这只是打败了目的。
第二点是你实际上是在为mssql类创建一个包装器,它增加了另一层复杂性,可能会引入错误并使维护变得更加困难。下一个处理这段代码的人会知道mssql,但不会知道你正在创建的类以及为实现它而必须实现的解决方法。
使用一个连接的最佳方式是将所有查询放入已连接的回调中
try {
fs.accessSync(__dirname + '/../../config.json');
let data = fs.readFileSync(__dirname + '/../../config.json')
data = JSON.parse(data);
storedUsername = data.sql.username;
storedPassword = data.sql.password;
storedServer = data.sql.server;
storedDatabase = data.sql.database;
} catch (e) {
// Actually you must do something here. If nothing else
// at least log it so that later on you are not left wondering
// why nothing seems to work.
}
var config = {
user: username || storedUsername || '',
password: password || storedPassword || '',
server: server || storedServer || 'localhost',
database: database || storedDatabase || '',
}
Database.connection = new mssql.Connection(config);
connection.connect(function(err) {
// do everything here
});
答案 1 :(得分:0)
module documentation中没有提到它,但您可以收听连接事件。因此,如果您希望保持结构有序并避免重复,您可以在Connection
上收听connect
事件。这对我来说似乎是完美的答案。
let mssql = require('mssql');
let fs = require('fs');
class Database
{
static connect(username, password, server, database)
{
if (Database.connection !== null) {
return Database.connection;
}
let storedUsername = null;
let storedPassword = null;
let storedServer = null;
let storedDatabase = null;
try {
fs.accessSync(__dirname + '/../../config.js');
let config = require(__dirname + '/../../config')
storedUsername = config.sql.username;
storedPassword = config.sql.password;
storedServer = config.sql.server;
storedDatabase = config.sql.database;
} catch (err) {
console.log(err);
}
let configuration = {
user: username || storedUsername || '',
password: password || storedPassword || '',
server: server || storedServer || 'localhost',
database: database || storedDatabase || '',
}
Database.connection = new mssql.Connection(configuration);
Database.connection.connect();
}
static disconnect()
{
Database.connection.close();
}
static getConnection()
{
if (Database.connection === null) {
try {
Database.connect();
} catch (e) {
throw new Error('Database.getConnection: Database not connected.');
}
}
return Database.connection;
}
static getInstance()
{
return mssql;
}
static query(query, fields)
{
if (typeof query !== 'string' || typeof fields !== 'object') {
throw new Error("Invalid parameters");
}
let db = Database.getInstance();
let connection = Database.getConnection();
let ps = new db.PreparedStatement(connection);
let values = {};
fields.forEach(function(current, index) {
ps.input(current.name, current.type);
values[current.name] = current.value;
});
connection.on('connect', function(err) {
if (err) {
throw err;
}
ps.prepare(query, function(err) {
if (err) {
throw new Error(err);
}
ps.execute(values, function(err, recordset, affected) {
if (err) {
ps.unprepare(function(err) {
if (err) {
throw new Error(err);
}
});
throw new Error(err);
}
ps.unprepare(function(err) {
if (err) {
throw new Error(err);
}
});
});
});
});
}
}
Database.connection = null;
module.exports = Database;
现在也许我应该在query()
方法中承诺那些回调。