Maison >interface Web >js tutoriel >Solution au problème d'erreur de pile d'appels maximale de nodejs
Cet article présente principalement le problème du dépassement de l'erreur de pile d'appels maximale par nodejs. Les amis dans le besoin peuvent s'y référer. J'espère que cela pourra aider tout le monde.
Le code implémenté par le programme est à peu près le suivant
function modify(cursor) { cursor.hasNext(function(err,bool) { if(err) { return console.log(err); } if(bool) { cursor.next(function(err, item){ if(err) { return console.log(err); } /* 此处为对数据进行update操作 */ // 递归调用modify方法 return modify(cursor); }); }else{ console.log('finished'); } }) } var cursor = collection.find(); modify(cursor);
Ensuite, laissez-le fonctionner lentement, mais quelque chose s'est produit qui m'a rendu déprimé. Lorsque le curseur a atteint près de 5 millions, le programme s'est écrasé, provoquant une erreur Uncaught RangeError : taille maximale de la pile d'appels dépassée
et m'a en fait dit que la pile avait explosé. Que s'est-il passé ? Hé, vérifie le code et commence à combler les trous. J'ai découvert que j'avais appelé modifier() de manière récursive ci-dessus et que le nombre de récursions était un peu petit (une table avec plus de 10 millions d'enregistrements). Il se peut que les appels récursifs constants de la fonction aient entraîné une augmentation continue de sa pile d'appels, et puis devenez de plus en plus gros, et finalement Il n'y en a plus, la pile explose. Il semble que nous devions donner au nœud une chance d'effectuer le garbage collection. Si nous voulons qu'il ait une chance d'effectuer le garbage collection, nous devons mettre fin à la récursion. Utilisez le setTimeout(); du système pour sortir de la pile d'appels récursifs.
Le code est modifié comme suit
function modify(cursor) { cursor.hasNext(function(err,bool) { if(err) { return console.log(err); } if(bool) { cursor.next(function(err, item){ if(err) { return console.log(err); } /* 此处对数据进行update操作 */ // 递归调用modify方法 return setTimeout(function(){ //跳出递归调用栈 modify(cursor); },0); }); }else{ console.log('finished'); } }) } var cursor = collection.find(); modify(cursor);
Essayez de l'exécuter. . . . ok, ça marche. Mais cela fonctionne un peu lentement, car je dois le faire sortir de la pile d'appels récursifs à chaque fois. Bien que cela soit acceptable, ce n'est pas nécessaire, car la pile n'explosera qu'après plus de 4 millions. Ajoutez un compteur et sortez-le lorsque la pile d'appels devient un peu grande.
var count = 0; function modify(cursor) { count++; cursor.hasNext(function(err,bool) { if(err) { return console.log(err); } if(bool) { cursor.next(function(err, item){ if(err) { return console.log(err); } /* 此处对数据进行update操作 */ // 递归调用modify方法 if(count%10000 === 0) { return setTimeout(function(){ //跳出递归调用栈 modify(cursor); },0); }else{ return modify(cursor); } }); }else{ console.log('finished'); } }) } var cursor = collection.find(); modify(cursor);
Recommandations associées :
Front-end avancé (6) : Observer la pile d'appels de fonction, la chaîne de portée et la fermeture
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!