Вам слід обернути свій рекурсивний виклик функції у файл
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() {
...
});