Вам слід обернути свій рекурсивний виклик функції у файл
setTimeout,
setImmediate або
process.nextTick
функція, щоб дати node.js можливість очистити стек. Якщо ви цього не зробите, і є багато циклів без реального виклику функції асинхронізації, або якщо ви не дочекаєтесь зворотного виклику, ваш результат RangeError: Maximum call stack size exceededбуде неминучим .
Є багато статей, що стосуються "Потенційного циклу асинхронізації". Ось один .
Тепер ще приклад коду:
var condition = false,
max = 1000000;
function potAsyncLoop( i, resume ) {
if( i < max ) {
if( condition ) {
someAsyncFunc( function( err, result ) {
potAsyncLoop( i+1, callback );
});
} else {
potAsyncLoop( i+1, resume );
}
} else {
resume();
}
}
potAsyncLoop( 0, function() {
...
});
Це правильно:
var condition = false,
max = 1000000;
function potAsyncLoop( i, resume ) {
if( i < max ) {
if( condition ) {
someAsyncFunc( function( err, result ) {
potAsyncLoop( i+1, callback );
});
} else {
setTimeout( function() {
potAsyncLoop( i+1, resume );
}, 0 );
}
} else {
resume();
}
}
potAsyncLoop( 0, function() {
...
});
Тепер ваш цикл може стати занадто повільним, тому що ми втрачаємо трохи часу (один оборотний перегляд браузера) за раунд. Але вам не потрібно телефонувати setTimeoutв кожному раунді. Зазвичай це нормально робити кожні 1000 разів. Але це може відрізнятися залежно від розміру вашого стека:
var condition = false,
max = 1000000;
function potAsyncLoop( i, resume ) {
if( i < max ) {
if( condition ) {
someAsyncFunc( function( err, result ) {
potAsyncLoop( i+1, callback );
});
} else {
if( i % 1000 === 0 ) {
setTimeout( function() {
potAsyncLoop( i+1, resume );
}, 0 );
} else {
potAsyncLoop( i+1, resume );
}
}
} else {
resume();
}
}
potAsyncLoop( 0, function() {
...
});