После того, как другие ответили, вы заявили, что вашей проблемой являются локальные переменные. Кажется, что простой способ сделать это - написать одну внешнюю функцию, которая будет содержать эти локальные переменные, затем использовать набор именованных внутренних функций и обращаться к ним по имени. Таким образом, вы всегда будете вкладывать только две глубины, независимо от того, сколько функций вам нужно соединить вместе.
Вот попытка моего новичка использовать 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 - я просто потратил пару часов на это. Но, может быть, с небольшой полировкой эта техника может помочь?