Depois que os outros responderam, você declarou que seu problema eram variáveis locais. Parece que uma maneira fácil de fazer isso é escrever uma função externa para conter essas variáveis locais, depois usar várias funções internas nomeadas e acessá-las pelo nome. Dessa forma, você apenas aninhará duas profundidades, independentemente de quantas funções você precise encadear.
Aqui está a tentativa do meu novato de usar o mysql
módulo Node.js com aninhamento:
function with_connection(sql, bindings, cb) {
pool.getConnection(function(err, conn) {
if (err) {
console.log("Error in with_connection (getConnection): " + JSON.stringify(err));
cb(true);
return;
}
conn.query(sql, bindings, function(err, results) {
if (err) {
console.log("Error in with_connection (query): " + JSON.stringify(err));
cb(true);
return;
}
console.log("with_connection results: " + JSON.stringify(results));
cb(false, results);
});
});
}
A seguir, é reescrita usando funções internas nomeadas. A função externa também with_connection
pode ser usada como suporte para variáveis locais. (Aqui, eu tenho os parâmetros sql
, bindings
, cb
que atuam de forma semelhante, mas você pode apenas definir algumas variáveis locais adicionais with_connection
.)
function with_connection(sql, bindings, cb) {
function getConnectionCb(err, conn) {
if (err) {
console.log("Error in with_connection/getConnectionCb: " + JSON.stringify(err));
cb(true);
return;
}
conn.query(sql, bindings, queryCb);
}
function queryCb(err, results) {
if (err) {
console.log("Error in with_connection/queryCb: " + JSON.stringify(err));
cb(true);
return;
}
cb(false, results);
}
pool.getConnection(getConnectionCb);
}
Eu pensava que talvez fosse possível criar um objeto com variáveis de instância e usá-las como um substituto para as variáveis locais. Mas agora acho que a abordagem acima, usando funções aninhadas e variáveis locais, é mais simples e fácil de entender. Demora algum tempo para desaprender OO, parece :-)
Então, aqui está minha versão anterior com um objeto e variáveis de instância.
function DbConnection(sql, bindings, cb) {
this.sql = sql;
this.bindings = bindings;
this.cb = cb;
}
DbConnection.prototype.getConnection = function(err, conn) {
var self = this;
if (err) {
console.log("Error in DbConnection.getConnection: " + JSON.stringify(err));
this.cb(true);
return;
}
conn.query(this.sql, this.bindings, function(err, results) { self.query(err, results); });
}
DbConnection.prototype.query = function(err, results) {
var self = this;
if (err) {
console.log("Error in DbConnection.query: " + JSON.stringify(err));
self.cb(true);
return;
}
console.log("DbConnection results: " + JSON.stringify(results));
self.cb(false, results);
}
function with_connection(sql, bindings, cb) {
var dbc = new DbConnection(sql, bindings, cb);
pool.getConnection(function (err, conn) { dbc.getConnection(err, conn); });
}
Acontece que isso bind
pode ser usado com alguma vantagem. Isso me permite livrar-me das funções anônimas um tanto feias que criei que não fizeram muito, exceto encaminhar-se para uma chamada de método. Não pude passar o método diretamente porque ele estaria envolvido com o valor errado de this
. Mas com bind
, eu posso especificar o valor this
que eu quero.
function DbConnection(sql, bindings, cb) {
this.sql = sql;
this.bindings = bindings;
this.cb = cb;
}
DbConnection.prototype.getConnection = function(err, conn) {
var f = this.query.bind(this);
if (err) {
console.log("Error in DbConnection.getConnection: " + JSON.stringify(err));
this.cb(true);
return;
}
conn.query(this.sql, this.bindings, f);
}
DbConnection.prototype.query = function(err, results) {
if (err) {
console.log("Error in DbConnection.query: " + JSON.stringify(err));
this.cb(true);
return;
}
console.log("DbConnection results: " + JSON.stringify(results));
this.cb(false, results);
}
// Get a connection from the pool, execute `sql` in it
// with the given `bindings`. Invoke `cb(true)` on error,
// invoke `cb(false, results)` on success. Here,
// `results` is an array of results from the query.
function with_connection(sql, bindings, cb) {
var dbc = new DbConnection(sql, bindings, cb);
var f = dbc.getConnection.bind(dbc);
pool.getConnection(f);
}
Obviamente, nada disso é JS adequado com a codificação Node.js. - passei algumas horas nele. Mas talvez com um pouco de polimento essa técnica possa ajudar?