Після того, як інші відповіли, ви заявили, що вашою проблемою були локальні змінні. Зрозуміло, що це простий спосіб - це написати одну зовнішню функцію, яка містить ці локальні змінні, а потім використовувати купу названих внутрішніх функцій та отримати доступ до них по імені. Таким чином, ви завжди гніздите лише дві глибокі, незалежно від того, скільки функцій вам потрібно зв'язати.
Ось моя спроба новачка використовувати mysql
модуль Node.js з вкладкою:
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);
});
});
}
Далі йде переписування, використовуючи названі внутрішні функції. Зовнішня функція також with_connection
може використовуватися як держатель для локальних змінних. (Ось, у мене є параметри sql
, bindings
, cb
які діють подібним чином, але ви можете просто визначити деякі додаткові локальні змінні 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);
}
Я думав, що, можливо, можна буде створити об'єкт зі змінними екземпляра та використовувати ці змінні екземпляри як заміну локальних змінних. Але тепер я вважаю, що вищезазначений підхід із використанням вкладених функцій та локальних змінних простіший і легший для розуміння. Треба трохи часу, щоб навчитися ОО, здається :-)
Отже ось моя попередня версія зі змінними об'єкта та екземпляра.
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); });
}
Виявляється, bind
можна скористатися якоюсь перевагою. Це дозволяє мені позбутися дещо потворних анонімних функцій, створених мною, які нічого не зробили, окрім як направити себе на виклик методу. Я не міг передати метод безпосередньо, оскільки він був би пов'язаний з неправильним значенням this
. Але з bind
, я можу вказати значення того, this
що я хочу.
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);
}
Звичайно, нічого з цього не є належним JS з кодуванням Node.js - я просто витратив на це пару годин. Але, може, з невеликим поліруванням ця техніка може допомогти?