Maison  >  Article  >  interface Web  >  Comment résoudre l'erreur de dépassement maximal de la pile d'appels dans nodejs

Comment résoudre l'erreur de dépassement maximal de la pile d'appels dans nodejs

亚连
亚连original
2018-06-15 11:27:141817parcourir

Cet article présente principalement le problème de nodejs dépassant l'erreur maximale de pile d'appels. Les amis qui en ont besoin peuvent s'y référer

Ce matin, le patron m'a dit que les données du projet précédent devaient être modifiées. , et chaque fichier de mongodb doit être mis à jour. Pour mettre à jour les enregistrements, vous pouvez écrire un script et l'exécuter.

Ensuite, je suis retourné silencieusement à l'ordinateur et la journée de dur labeur a recommencé. Le volume de données de cette table étant un peu important, il devrait y avoir plus de 10 millions d'enregistrements. Pensez donc à utiliser le curseur de mongodb pour parcourir et modifier.

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);

J'ai compilé ce qui précède pour vous, j'espère que cela vous sera utile à l'avenir.

Articles associés :

Comment utiliser la méthode Generator en JavaScript

Comment changer l'avatar dans node

Un problème 404 se produit lors de l'actualisation de la page dans React-Router

Introduction détaillée à l'utilisation de la capture du modificateur d'événement Vue

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn