ホームページ  >  記事  >  ウェブフロントエンド  >  Nodejs が最大コール スタックを超えるエラーの問題の解決策

Nodejs が最大コール スタックを超えるエラーの問題の解決策

小云云
小云云オリジナル
2017-12-27 13:56:451696ブラウズ

この記事は主にnodejsの最大コールスタックエラーの問題を紹介していますので、困っている方は参考にしていただければ幸いです。

プログラムの実装コードはおおよそ以下の通りです


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

それではゆっくり実行させていただきましたが、落ち込むような出来事が起こりました。カーソルが 500 万近くに達すると、プログラムがクラッシュし、Uncaught RangeError: Maximum call stack sizeowned

というメッセージが表示され、実際にスタックが爆発したことが示されました。何が起こったのでしょうか? コードをチェックして、穴を埋め始めてください。上記で、modify() を再帰的に呼び出したことがわかりましたが、再帰の数は少し少なかったです (1,000 万を超えるレコードを持つテーブル)。おそらく、関数の定期的な再帰呼び出しによって呼び出しスタックが増加し続けた可能性があります。それからどんどん大きくなり、最後にはもう限界があり、スタックが爆発します。ノードにガベージ コレクションを実行する機会を与える必要があるようです。ガベージ コレクションを実行する機会を与えたい場合は、再帰を終了する必要があります。システムの setTimeout() を使用して、再帰呼び出しスタックから抜け出します。

以下のようにコードを修正します


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

実行後試してみてください。 。 。 。わかりました、うまくいきます。ただし、毎回再帰呼び出しスタックからジャンプする必要があるため、実行が少し遅くなります。これは問題ありませんが、スタックが 400 万を超えると爆発するだけなので、必須ではありません。カウンターを追加し、呼び出しスタックが少し大きくなったらポップアウトします。


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

関連する推奨事項:

JavaScript 呼び出しスタック、末尾再帰、手動最適化の詳細な紹介

フロントエンドの上級 (6): 関数呼び出しスタック、スコープ チェーン、クロージャを観察する

上級フロントエンドの基礎 (6): Chrome デベロッパー ツールで関数呼び出しスタック、スコープ チェーン、クロージャを観察します

以上がNodejs が最大コール スタックを超えるエラーの問題の解決策の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。