Функция f1 () выполняет асинхронную работу, а затем вызывает функцию обратного вызова ('child') с результатами. Результаты проверяются обратным вызовом, и если они оказываются непригодными, обратный вызов должен вызвать f1 () еще раз. Это должно происходить до тех пор, пока подходящие результаты не будут возвращены из f1 ().

Как правильно сделать это в NodeJS? Мое текущее решение:

function f1( args, callback ) {
  // do async job
  callback(answ); // answ is returned by async job
}


var args;
// prepare args

function f2(answ) {
  if ( anws ) return true; // Urahh, all ok
  // change args and try next call
  f1(args, f2);
}

f1( args, f2 );
0
rlib 17 Дек 2015 в 17:32

4 ответа

Лучший ответ

Я думаю, что это лучший дизайн

function f1(a, callback) {
  console.log(a);
  callback(a, f1);              // callback points to f2
}

function f2(a, callback) {
  if (a >= 10) return;
  callback(a+1, f2);            // callback points to f1
}

// initial args = 0
f1(0,f2);

Таким образом, у вас нет внешнего состояния (args в вашем коде). f2 по-прежнему заботится о настройке аргументов, но изменения (a+1 в моем коде) передаются непосредственно в функцию, которая вызывается.

Кроме того, f1 указывает себя в обратном вызове как функцию, которая должна вызываться в случае, когда должен иметь место цикл. Таким образом, f2 может использоваться для любого «родителя», который может вызывать его, пока родитель передает ссылку на себя.

Довольно классные вещи.

Выход

0 1 2 3 4 5 6 7 8 9 10

Подсказка: нет смысла возвращать true в ваш f2. Возвращаемое значение асинхронного вызова нигде не может быть использовано

1
Thank you 17 Дек 2015 в 15:17

Я думаю, что ваше решение может работать. Однако это зависит от контекста, в котором вы работаете. Я предлагаю вам использовать process.nextTick () для обработки этого типа "рекурсии" https://nodejs.org/docs/latest/api/process.html#process_process_nextk

Если вы хотите быть действительно асинхронным, важно написать код без блокировки в nodejs.

-2
Maksim 17 Дек 2015 в 14:48

Ваше решение работает, но я обычно использую обещание в этом случае.

Почему? Потому что это, как правило, более податливым и избегать попадания в "ад обратного вызова".

Теперь он работает изначально на Node 5.0 благодаря спецификации ES6:

https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Promise

Для вашего случая, я думаю, что-то подобное должно работать:

function promiselauch(arg){
 new Promise(function( resolve,reject ) {
  // do async job
  if(answ)
   resolve(answ); // answ is returned by async job
  else
   reject(answ)
}).then(function(anws){
   // Urahh, all ok do what you want
}, function(anws){
 promiselauch(anws); //fail so relaunch
}); 
}
promiselaunch(args); 

Не тестировал, адаптировал это к идее.

-1
Julien Leray 17 Дек 2015 в 15:15

Не уверен, что это идеальный поток, но это сработает.

function async () {
    return async_promise;
}

function run_async (args) {
    async(args).then(success, run_async.bind(null, args));
}

function success () {
    // fin
}

run_async(args);

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

0
lededje 17 Дек 2015 в 14:47