Po udzieleniu odpowiedzi przez innych stwierdziłeś, że Twoim problemem są zmienne lokalne. Wydaje się, że prostym sposobem na zrobienie tego jest napisanie jednej zewnętrznej funkcji, która będzie zawierała te zmienne lokalne, a następnie użycie zestawu nazwanych funkcji wewnętrznych i dostęp do nich po nazwie. W ten sposób zagnieżdżasz tylko dwie głębokie, niezależnie od tego, ile funkcji musisz połączyć w łańcuch.
Oto próba mojego początkującego wykorzystania mysql
modułu Node.js z zagnieżdżeniem:
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);
});
});
}
Poniżej przedstawiono przepisanie przy użyciu nazwanych funkcji wewnętrznych. Funkcja zewnętrzna with_connection
może być również używana jako uchwyt na zmienne lokalne. (Tutaj, mam parametry sql
, bindings
, cb
że działają w podobny sposób, ale można po prostu zdefiniować dodatkowe zmienne lokalne w 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);
}
Myślałem, że być może byłoby możliwe stworzenie obiektu ze zmiennymi instancji i użycie tych zmiennych instancji jako zamienników zmiennych lokalnych. Ale teraz stwierdzam, że powyższe podejście wykorzystujące funkcje zagnieżdżone i zmienne lokalne jest prostsze i łatwiejsze do zrozumienia. Oduczenie się OO zajmuje trochę czasu :-)
Oto moja poprzednia wersja ze zmiennymi obiektu i instancji.
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); });
}
Okazuje się, że bind
można to wykorzystać z pewną korzyścią. Pozwala mi pozbyć się nieco brzydkich anonimowych funkcji, które stworzyłem, które niewiele robiły, z wyjątkiem przekazywania samych siebie do wywołania metody. Nie mogłem przekazać metody bezpośrednio, ponieważ wiązałoby się to z niewłaściwą wartością this
. Ale za pomocą bind
mogę określić wartość this
, której chcę.
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);
}
Oczywiście nic z tego nie jest poprawnym JS z kodowaniem Node.js - spędziłem nad tym tylko kilka godzin. Ale może przy odrobinie dopracowania ta technika może pomóc?