Sie sollten Ihre rekursiven Funktionsaufruf in eine
setTimeout
, wickeln
setImmediate
oder
process.nextTick
Funktion node.js die Möglichkeit zu geben, den Stapel zu löschen. Wenn Sie dies nicht tun und es gibt viele Schleifen ohne real async Funktionsaufruf oder wenn Sie nicht auf den Rückruf warten, wird Ihre RangeError: Maximum call stack size exceeded
unvermeidlich sein.
Es gibt viele Artikel über "Potential Async Loop". Here is one.
nun einige weitere Beispiel-Code:
Dieses Recht ist:
var condition = false, // potential means "maybe never"
max = 1000000;
function potAsyncLoop(i, resume) {
if(i < max) {
if(condition) {
someAsyncFunc(function(err, result) {
potAsyncLoop(i+1, callback);
});
} else {
// Now the browser gets the chance to clear the stack
// after every round by getting the control back.
// Afterwards the loop continues
setTimeout(function() {
potAsyncLoop(i+1, resume);
}, 0);
}
} else {
resume();
}
}
potAsyncLoop(0, function() {
// code after the loop
...
});
Jetzt ist Ihre Schleife zu langsam werden könnte, weil wir ein wenig Zeit (ein Browser hin und zurück) pro Runde verlieren. Aber Sie müssen setTimeout
in jeder Runde nicht anrufen. Normalerweise ist es o.k. um es alle 1000 Mal zu tun. Aber diese unterscheiden sich möglicherweise auf Ihrem Stack-Größe abhängig:
var condition = false, // potential means "maybe never"
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() {
// code after the loop
...
});
Warum brauchen Sie solche tiefe Rekursion überhaupt? –
Bitte, können Sie etwas Code posten? 'Segmentation fault: 11' bedeutet normalerweise ein Fehler im Knoten. – vkurchatkin
@Dan Abramov: Warum tiefe Rekursion? Dies kann ein Problem sein, wenn Sie über ein Array oder eine Liste iterieren und eine asynchrone Operation für jeden (z. B. eine Datenbankoperation) ausführen möchten. Wenn Sie den Rückruf der asynchronen Operation verwenden, um zum nächsten Element zu gelangen, wird für jedes Element in der Liste mindestens eine zusätzliche Rekursionsebene vorhanden sein. Das unten von heinob bereitgestellte Anti-Pattern verhindert, dass der Stack ausbläst. –