Sie sollten Ihren rekursiven Funktionsaufruf in a einschließen
setTimeout
,
setImmediate
oder
process.nextTick
Funktion, um node.js die Möglichkeit zu geben, den Stapel zu löschen. Wenn Sie dies nicht tun und es viele Schleifen ohne echten asynchronen Funktionsaufruf gibt oder wenn Sie nicht auf den Rückruf warten, RangeError: Maximum call stack size exceeded
ist dies unvermeidlich .
Es gibt viele Artikel zum Thema "Potential Async Loop". Hier ist einer .
Nun noch ein Beispielcode:
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() {
...
});
Dies ist richtig:
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() {
...
});
Jetzt wird Ihre Schleife möglicherweise zu langsam, da wir pro Runde etwas Zeit verlieren (ein Browser-Roundtrip). Sie müssen aber nicht setTimeout
in jeder Runde anrufen . Normalerweise ist es in Ordnung, dies alle 1000. Mal zu tun. Dies kann jedoch je nach Stapelgröße unterschiedlich sein:
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() {
...
});