2016-06-13 16 views
0

移行手順は2〜3日かかる場合があります。私は、次の実装ではStackOverFlow例外が再帰的に発生する可能性があることを憂慮しています。このコードを実行するためにJavaScriptは実際には巨大なスタックを構築していますか?もしそうなら、より良い実装は何でしょうか?私は約10百万回このサービスを呼び出すかもしれません。JavaScriptで再帰的にWebサービスを呼び出すと、StackOverflowが発生する

function mainFunc() { 
     var url = getMyUrl(); 
     $.ajax({ 
      url: url, 
      type: "POST", 
      contentType: "application/json;charset=utf-8", 
      dataType: "json", 
      success: function (remaining) { 
       if(remaining > 0) { 
        mainFunc(); 
       } 
       else { 
        alert('done'); 
       } 
      }, 
      error: function (x, e) { 
       alert('error!'); 
      } 
     }); 
    } 

答えて

1

まず、これはブラウザから行うべきもののようには聞こえませんが、代わりにサーバー側を処理します。

あなたの再帰は非同期的に起こっているので、スタックオーバーフローは確実に起こりません。
正確なコード(具体的には、どの値がクロージャに正確に含まれているか)によっては、メモリの蓄積が開始されることがあります。 mainFuncを呼び出すたびに、成功とエラー機能が再作成されるため、メモリーを追加使用することもできます。

これらの関数をmainFuncの外に宣言し、mainFunc関数内で参照を渡すことで、この関数のメモリ割り当ての問題をかなり簡単に解決できます。

これを実行しても、コースからのメモリ例外を完全に防ぐことはできません。これは実際には実際のコードと、各繰り返しでどの参照が保持されているかによって異なります。

この長いプロセスでコードがリソースに掛かっているかどうかを判断するには、コードを読んで、コードがどこから漏れているのかを把握するか、メモリプロファイリングオプションを参照してください:

https://developer.chrome.com/devtools/docs/javascript-memory-profiling

例くくり出すために閉鎖:

function mainFuncSuccess(remaining) { 
    if(remaining > 0) { 
     mainFunc(); 
    } 
    else { 
     alert('done'); 
    } 
} 


function mainFuncError() { 
    alert('error!'); 
} 

function mainFunc() { 
     var url = getMyUrl(); 
     $.ajax({ 
      url: url, 
      type: "POST", 
      contentType: "application/json;charset=utf-8", 
      dataType: "json", 
      success: mainFuncSuccess, 
      error: mainFuncError 
     }); 
    } 
+0

このような機能を外部で宣言していますか? 'success:callSuccess(remaining);' 'callSuccess'は' mainFunc() 'を呼び出します。 – yazanpro

+1

@yazanproいいえ、私の更新された答えを見てください –

+0

'main'を' mainFuncSuccess'のパラメータとして使うことができますか? 'remaining'は今では未定義です。 – yazanpro

1

$.ajaxは非同期であるため、それは、リモートサーバが応答するまでsuccess機能を呼び出すことはありません。言い換えれば、各反復の後、JSエンジンは本質的に応答を得るまでスリープしてから、success機能で再開します。ですから、これは技術的に再帰の例ではありません。スタックは、それが何回繰り返しても(スタックに寄与していない他の要素がないと仮定して)、かなり小さくなければなりません。

1

いいえ、後で使用する必要がmainFuncの内側に何かを格納していないので。関数のスコープに格納する必要のあるオブジェクトはありません。

クロムでは、window.performance.memoryでメモリを確認できます

+0

スタックオーバーフロー(try '(function foo(){foo();})()')を得​​るために、関数の外部に何も格納する必要はありません。 –

+0

これは単純な例ですが、実際にはコードがどのように見えるかによって決まります。 –

関連する問題