Могу ли я выполнить много асинхронных запросов к базе данных без глубокого вложения моего кода? - PullRequest
2 голосов
/ 14 ноября 2011

Я новичок в программировании асинхронно. Я столкнулся с ситуацией, когда мне нужно выполнить 8 поисков в базе данных в цикле. Я не уверен, как это сделать - моя библиотека базы данных возвращает данные в функции обратного вызова, и я не могу продолжить работу с моим кодом, пока у меня не будет всех 8 строк, поэтому мне нужно остановить до тех пор, пока все 8 поисков не завершатся. *

Это то, что я сейчас себе представляю:

db.world.Queue.find(@user.kingdom.troops_queue).on 'success', (troops_queue) ->
    db.world.Queue.find(@user.kingdom.tanks_queue).on 'success', (tanks_queue) ->
        #etc etc

Это ужасно и грубо, конечно, но я не могу придумать, как свернуть его в цикл, который позволит моему коду приостанавливаться и продолжаться только после заполнения последнего элемента. Я изучал такие вещи, как функция .each () jQuery, но каково поведение этой функции? Продолжается ли код после того, как он немедленно продолжается, или он ожидает завершения цикла?

Ответы [ 5 ]

9 голосов
/ 14 ноября 2011

Есть два часто используемых способа. Первый использует библиотеку вроде caolans async :

async.parallel
  a: (cb) -> doTaskA cb
  b: (cb) -> doTaskB cb
, (err, {a, b}) ->
  # you can use err, a and b here now

Второй подход: streamlinejs :

troops_queue = db.world.Queue.find(@user.kingdom.troops_queue).on 'success', _
tanks_queue = db.world.Queue.find(@user.kingdom.tanks_queue).on 'success', _
# go on here

Однако оба решения предполагают, что первым аргументом обратного вызова является ошибка - если это не так, вам следует обратиться к автору библиотеки, которую вы используете, чтобы изменить его.

1 голос
/ 14 ноября 2011

Я всегда использую Шаг для своих проектов, это очень чисто и красиво.

Вот пример некоторых обратных вызовов подряд:

Step(
  function readSelf() {
    fs.readFile(__filename, this);
  },
  function capitalize(err, text) {
    if (err) throw err;
    return text.toUpperCase();
  },
  function showIt(err, newText) {
    if (err) throw err;
    console.log(newText);
  }
);

Вы можетеТакже я хочу сделать что-то параллельное и только потом вызвать обратный вызов, к счастью, this.parallel () как раз для этого:

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);
  }
)
1 голос
/ 14 ноября 2011

Вы можете организовать свои запросы в последовательности «успешной прогрессии»;эта последовательность может использоваться в цикле в стиле продолжения, как в Javascript:

var lookups = [
   function(){ Q.find(@user.kingdom.troops_queue; },
   function(troops_queue){ Q.find(...tanks_queue; },
   function(tanks_queue){ Q.find(...next_queu; },
   ....
];

И эта «многослойная» последовательность может быть извлечена через асинхронную мельницу, например

function proceedOn( sequence, previous_result ) {       
   var first = sequence[0];
   first( previous_result ).onSuccess( function(result){
     proceedOn( sequence[1..], result );
   } );
}

proceedOn( lookups );

(Где я взял некоторые поэтические вольности на массив синтаксического сахара)

1 голос
/ 14 ноября 2011

Использовать управление потоком, как after.js

var data = {};
    cb = after(8, function ( ) {
        // handle all 8 results
    }),
    queue = db.world.Queue,
    kingdom = this.user.kingdom;

queue.find(kingdom.troops_queue).on('success', function (result) {
    data["troops_queue"] = result;
    cb();
});

// etc

P.S. Я исправил этот код для вас.

0 голосов
/ 14 ноября 2011

Поскольку вы пометили "coffescript" некоторыми ссылками, которые вы можете проверить (длинные темы!): выпуск241 , выпуск287 , выпуск350 , выпуск1710 (и, возможно, еще ...)

В двух словах:

  • Пользователь создал этот форк , но он больше не поддерживается.
  • Tamejs или streamlinejs пока считаются хорошими альтернативами.
...