Цель работы с узлом - не заботиться о том, в каком порядке происходят события. Это может усложнить некоторые сценарии. Нет никакого позора во вложенных обратных вызовах. Как только вы привыкнете к тому, как это выглядит, вы можете обнаружить, что действительно предпочитаете этот стиль. Я делаю; очень ясно, какие обратные вызовы заказа сработают. Вы можете отказаться от анонимных функций, чтобы сделать их менее многословными, если это необходимо.
Если вы хотите немного реструктурировать свой код, вы можете использовать «типичный» вложенный метод обратного вызова. Если вы хотите избежать обратных вызовов, существует множество асинхронных сред, которые попытаются помочь вам в этом. Один из них, который вы можете проверить, - async.js (https://github.com/fjakobs/async.js). Пример каждого:
app.get('/home', function (req,res) {
var lock = 2;
var result = {};
result.user_array = [];
result.title_array = [];
var finishRequest = function(result) {
req.session.title_array = result.title_array;
req.session.user_array = result.user_array;
res.render('home.ejs', {layout: false, locals: { user_name: result.user_array, title: result.title_array }});
};
// first query
var q1 = function(fn) {
var sql = 'select user_name from users';
db.execute(sql)
.addListener('row', function(r) {
result.user_array.push( { user_name: r.user_name } );
})
.addListener('result', function(r) {
return fn && fn(null, result);
});
};
// second query
var q2 = function(fn) {
var sql = 'select title from code_samples';
db.execute(sql)
.addListener('row', function(r) {
result.title_array.push( { title: r.title } );
})
.addListener('result', function(r) {
return fn && fn(null, result);
});
}
//Standard nested callbacks
q1(function (err, result) {
if (err) { return; //do something}
q2(function (err, result) {
if (err) { return; //do something}
finishRequest(result);
});
});
//Using async.js
async.list([
q1,
q2,
]).call().end(function(err, result) {
finishRequest(result);
});
});
Для одноразового использования я бы, вероятно, просто использовал бы метод подсчета ссылок. Просто отследите, сколько запросов вы хотите выполнить, и обработайте ответ, когда все они будут завершены.
app.get('/home', function (req,res) {
var lock = 2;
var user_array = [];
var title_array = [];
var finishRequest = function() {
res.render('home.ejs', {layout: false, locals: { user_name: user_array, title: title_array }});
}
// first query
var sql = 'select user_name from users';
db.execute(sql)
.addListener('row', function(r) {
user_array.push( { user_name: r.user_name } );
})
.addListener('result', function(r) {
req.session.user_array = user_array;
lock -= 1;
if (lock === 0) {
finishRequest();
}
});
// second query
var sql = 'select title from code_samples';
db.execute(sql)
.addListener('row', function(r) {
title_array.push( { title: r.title } );
})
.addListener('result', function(r) {
req.session.title_array = title_array;
lock -= 1;
if (lock === 0) {
finishRequest();
}
});
});
Еще более приятный подход состоял бы в том, чтобы просто вызывать finishRequest () в каждом обратном вызове «result» проверку непустых массивов до того, как вы обработаете ответ. Будет ли это работать в вашем случае, зависит от ваших требований.