Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
function first(foo1, foo2, externalCallback) {
db.query("...", second.bind(foo1, foo2, externalCallback))
}
function second(foo1, foo2, externalCallback, res) {
var someResult = ... // какой-то крутой алгоритм, которому нужен res
db.query("...", third.bind(someResult, foo1, foo2, externalCallback, res))
}
function third(someResult, foo1, foo2, externalCallback, res) {
// заканчиваем
db.query("...", externalCallback.bind(someResult, res))
}
Object[] first(foo1, foo2) {
Res res = db.query("...");
List someResult = // крутой алгоритм с res
res = db.query("...");
// заканчиваем
Res res2 = db.query("...");
return new Object[] {someResult, res2};
}
Юзайте синхронные варианты функций в node.js, и у вас будет точно такой же код на JS.
struct Example {
void *exec_ptr;
Task<String> *a;
Task<String> *b;
void run() {
resume();
a = db_query("query one");
b = db_query("query two");
wait(a, b);
render("template.html", a->result(), b->result());
}
};
@myubertaskframework.task
def run():
a = db_query("query one")
b = db_query("query two")
yield wait(a, b)
render("template.html", a, b)
async Task MyAsyncExample() {
List<Task<String>> tasks = new List<Task<String>>() {
db.query("query one");
db.query("query two");
}
String[] results = await TaskEx.WhenAll<String>(tasks);
tpl.render("template.html", results);
}
Вариант на ноде:
Future( ()=> {
var a = db_query( "query one" )
var b = db_query( "query two" )
render( "template.html" , a.wait(), b.wait() )
}).detach()
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
QueryResult res1 = db.query("SELECT COUNT(id) FROM books");
QueryResult res2 = db.query("SELECT * FROM books LIMIT " + Integer.parseInt(limit) + " OFFSET " + Integer.parseInt(offset));
QueryResult res3 = db.query("SELECT * FROM bookData WHERE bookId IN (" + StringUtils.join(ids, ",") + ")");
dataset.render(resp);
}
В кратце — для того, чтобы не блокировать процесс ожиданием ответа бд или фс или любого другого внешнего ресурса.
Если перенести на клиент — представьте что вы выполняете синхронный ajax request
Пока наружные утилиты работают ваш js сервер продолжает обслуживать реквесты и раздавать задачи внешним утилитам.
class SecondQuery extends Thread {
public QueryResult result;
@Override public void run() {
result = db.query("second query text");
}
}
SecondQuery secondQuery = new SecondQuery();
secondQuery.start();
QueryResult firstResult = qb.query("first query text");
secondQuery.join();
QueryResult thirdResult = qb.query("third query text");
Ну, если общее время ответа вас не заботит — то, конечно, нет таких ситуаций.
Экономия не в памяти, а в неблокирующем доступе к ресурсу.
Далеко не к каждой.
exports.processRequest = Sync( function (request, response)
{
var res1 = db.query('SELECT COUNT(id) FROM books' );
// do something
var res2 = db.query('SELECT * FROM books LIMIT ' + Number(limit) + ' OFFSET' + Number(offset) );
// do something 2
var res3 = db.query('SELECT * FROM bookData WHERE bookId IN (' + ids.join(', ') + ')' );
// И вот наконец формируем как-то dataset
response.write(render(dataset));
} );
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
QueryResult res1 = db.query("SELECT COUNT(id) FROM books");
QueryResult res2 = db.query("SELECT * FROM books LIMIT " + Integer.parseInt(limit) + " OFFSET " + Integer.parseInt(offset));
QueryResult res3 = db.query("SELECT * FROM bookData WHERE bookId IN (" + StringUtils.join(ids, ",") + ")");
dataset.render(resp);
}
exports.processRequest = function (request, response) {
Step(
function getBookCount(){
db.query('SELECT COUNT(id) FROM books', this);
},
function getBooks(err, count){
if(err) throw err;
db.query('SELECT * FROM bookData WHERE bookId IN (' + ids.join(', ') + ')', this);
},
function getMetaData(err, ids){
if(err) throw err;
db.query('SELECT * FROM bookData WHERE bookId IN (' + ids.join(', ') + ')', this);
},
function result(err, meta){
return response(err, meta);
}
);
Step(
// Loads two files in parallel
function loadStuff() {
fs.readFile(__filename, this.parallel());
fs.readFile("/etc/passwd", this.parallel());
},
// Show the result when done
function showStuff(err, code, users) {
if (err) throw err;
console.log(code);
console.log(users);
}
)
@defer.inlineCallbacks
def someFunction():
a = 1
b = yield deferredReturningFunction(a)
c = yield anotherDeferredReturningFunction(a, b)
defer.returnValue( c )
@defer.inlineCallbacks аннотация и yield перед вызовом асинхронного метода.
exports.processRequest = function (request, response) {
var dataset = {};
getBookCount();
function getBookCount () {
db.query('SELECT COUNT(id) FROM books', onBookCountReady);
}
function onBookCountReady (res) {
// ...заполняем dataset
getBooks();
}
// поскипано
}
@defer.inlineCallbacks
def someFunction():
a = 1
b = yield deferredReturningFunction(a)
c = yield anotherDeferredReturningFunction(a, b)
defer.returnValue( c )
@defer.inlineCallbacks
def processRequest(request):
dataset = Dataset()
count = yield db.query('SELECT COUNT(id) FROM books')
// заполняем dataset
books = yield db.query('SELECT * FROM books LIMIT ' + dataset.limit + ' OFFSET ' + dataset.offset)
// заполняем dataset
meta = yield db.query('SELECT * FROM bookData WHERE bookId IN (' + dataset.ids.join(', ') + ')');
// ... заполняем dataset
defer.returnValue(Render(dataset));
«Лапша» из callback-ов — будьте проще