Maison >interface Web >js tutoriel >Solution au problème d'erreur de pile d'appels maximale de nodejs

Solution au problème d'erreur de pile d'appels maximale de nodejs

小云云
小云云original
2017-12-27 13:56:451746parcourir

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 :

Introduction détaillée à la pile d'appels JavaScript, à la récursivité de queue et à l'optimisation manuelle

Front-end avancé (6) : Observer la pile d'appels de fonction, la chaîne de portée et la fermeture

Front-end basique avancé (6) : Observer les fonctions dans les outils de développement Chrome Pile d'appels , chaîne de portée et 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!

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