Après que les autres ont répondu, vous avez déclaré que votre problème était des variables locales. Il semble qu'un moyen facile de le faire est d'écrire une fonction externe pour contenir ces variables locales, puis d'utiliser un tas de fonctions internes nommées et d'y accéder par leur nom. De cette façon, vous n'en nicherez que deux en profondeur, quel que soit le nombre de fonctions dont vous avez besoin pour enchaîner.
Voici la tentative de mon débutant d'utiliser le mysql
module Node.js avec l'imbrication:
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);
});
});
}
Ce qui suit est une réécriture utilisant des fonctions internes nommées. La fonction externe with_connection
peut également être utilisée comme support pour les variables locales. (Ici, j'ai les paramètres sql
, bindings
, cb
qui agissent de la même manière, mais vous pouvez définir quelques - unes des variables locales supplémentaires 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);
}
J'avais pensé qu'il serait peut-être possible de créer un objet avec des variables d'instance et d'utiliser ces variables d'instance en remplacement des variables locales. Mais maintenant, je trouve que l'approche ci-dessus utilisant des fonctions imbriquées et des variables locales est plus simple et plus facile à comprendre. Il faut du temps pour désapprendre OO, il semble :-)
Voici donc ma version précédente avec un objet et des variables d'instance.
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); });
}
Il s'avère que cela bind
peut être utilisé à un certain avantage. Cela me permet de me débarrasser des fonctions anonymes quelque peu laides que j'ai créées et qui n'ont rien fait, sauf pour se transmettre à un appel de méthode. Je n'ai pas pu passer la méthode directement car elle aurait été impliquée avec la mauvaise valeur de this
. Mais avec bind
, je peux spécifier la valeur de ce this
que je veux.
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);
}
Bien sûr, rien de tout cela n'est correct JS avec le codage Node.js - je viens de passer quelques heures dessus. Mais peut-être qu'avec un peu de polissage, cette technique peut vous aider?