Después de que los demás respondieron, usted declaró que su problema eran variables locales. Parece que una manera fácil de hacer esto es escribir una función externa para contener esas variables locales, luego usar un grupo de funciones internas con nombre y acceder a ellas por nombre. De esta manera, solo anidará dos de profundidad, independientemente de cuántas funciones necesite encadenar.
Aquí está el intento de mi novato de usar el mysql
módulo Node.js con anidamiento:
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);
});
});
}
La siguiente es una reescritura utilizando funciones internas con nombre. La función externa también with_connection
se puede utilizar como soporte para variables locales. (Aquí, tengo los parámetros sql
, bindings
, cb
que actúan de una manera similar, pero sólo se puede definir algunas variables locales adicionales en 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);
}
Había estado pensando que quizás sería posible hacer un objeto con variables de instancia, y usar estas variables de instancia como reemplazo de las variables locales. Pero ahora encuentro que el enfoque anterior que usa funciones anidadas y variables locales es más simple y más fácil de entender. Se necesita un tiempo para desaprender OO, parece :-)
Así que aquí está mi versión anterior con un objeto y variables de instancia.
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); });
}
Resulta que bind
se puede utilizar con alguna ventaja. Me permite deshacerme de las funciones anónimas algo feas que he creado que no hicieron mucho, excepto reenviarme a una llamada al método. No pude pasar el método directamente porque habría estado involucrado con el valor incorrecto de this
. Pero con bind
, puedo especificar el valor this
que quiero.
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);
}
Por supuesto, nada de esto es JS adecuado con la codificación Node.js, solo pasé un par de horas en ello. ¿Pero tal vez con un poco de pulido esta técnica puede ayudar?