再帰関数呼び出しをにラップする必要があります
setTimeout
、
setImmediate
または
process.nextTick
node.jsにスタックをクリアする機会を与える関数。それを行わず、実際の非同期関数呼び出しなしで多くのループがある場合、またはコールバックを待たない場合、あなたRangeError: Maximum call stack size exceeded
は避けられません。
「PotentialAsyncLoop」に関する記事はたくさんあります。これが1つです。
次に、もう少しサンプルコードを示します。
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() {
...
});
これで、ラウンドごとに少しの時間(1つのブラウザーラウンドトリップ)が失われるため、ループが遅くなりすぎる可能性があります。ただし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() {
...
});