2013-07-12 5 views
4

Начиная с express и mongoose Мне часто приходится выполнять некоторые пакетные операции над коллекциями. Однако он обычно включает обратные вызовы, которые представляют собой боль, учитывая, как параллелизм кодируется в nodejs. поэтому в основномАсинхронная и рекурсия в узлах

//given a collection C 
var i = 0; 
var doRecursive = function(i){ 
    if(i<C.length){ 
     C[i].callAsync(err,result){ 
     i=+1; 
     return doRecursive(i); 
     } 
    }else{ 
     return done(); 
    } 
} 
doRecursive(i); 

Теперь я не помню, что это максимальный стек, прежде чем я получаю поток stackover с узлом, но я думаю, с 10 000 элементов, она не будет делать. Интересно, есть ли другие способы справиться с этим, если да, каковы они? спасибо

+1

Ну, асинхронные функции помогут переполнению стека в качестве обратного вызова будет в другом стек вызовов. Но, выйдя в другой стек, он «возвращает» бесполезно. –

+1

взгляните на [async] (https://github.com/caolan/async) –

ответ

5

Если цель состоит в асинхронной итерации коллекции, доступно множество библиотек потока управления.

Хорошим примером является async и его reduce function:

async.reduce(C, 0, function (memo, item, callback) { 
    item.callAsync(function (err, result) { 
     if (err) { 
      callback(err); 
     } else { 
      callback(null, memo + result); 
     } 
    }); 
}, function (err, result) { 
    // ... 
}); 

Примечание: Это не совсем понятно, какое значение вы хотели бы получить от doRecursion, так что это просто использует дополнение для примера.

+0

Я знаю асинхронный. у async есть способ обобщить рекурсию, чтобы рекурсия могла быть написана «красивее»? Люди говорят мне, что не должно быть проблем с stackoverflow с рекурсивными и асинхронными вызовами, я должен проверить это, чтобы быть уверенным. EDIT: я вижу, вы используете Async.reduce, интересно, не знали об этом. – mpm

1

я думаю, что вы можете просто самостоятельна итерацию вместо истинной рекурсии, так как вы не сверлить в глубокий объект:

function doRecursive (C, i){ 
    i=i||0; 
    if(i<C.length){ 
     C[i].callAsync(err, function(result){ 
      doRecursive(C, ++i); 
     }); 
    }else{ 
     done(); 
    } 
}; 

doRecursive(C); 

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

doRecursive(C, ++i); 

в

setTimeout(doRecursive.bind(this, C, ++i), 50); 
Смежные вопросы