2

私はこれに1日苦労しています.サークルに入って助けていただければ幸いです:-)

Abstract
非同期 ajax は、このペアに対して dns 解決を返すために、リゾルバーと fqdn 変数を使用して cgi を呼び出します。(dig @resolver $fqdn の出力を返します)

問題
Firebug では、get リクエストが非同期で起動され、ブラウザへのレスポンスが期待どおりであることを確認できます。ただし、onreadystatechange はオブジェクトを認識しないため、ドキュメントの正しい div に応答を配置できません。

補足事項
オブジェクトの配列を反復処理しているという事実は別として、反復間に遅延が設定されている場合でも、それらはすべて瞬時に起動されるようです。

以下は私のコメント付きのコード
です。リゾルバーは配列であるため、xmlhttprequest オブジェクトの配列を作成しました。

function resolve() { 
     var numofres = 6;
     var arr = new Array;
     arr[0] = "192.168.1.11";
     arr[1] = "8.8.8.8";
     arr[2] = "8.8.4.4";
     arr[3] = "159.134.0.1";
     arr[4] = "159.134.0.2";
     var len = arr.length;
     var ax  = new Array(); //creating ax as an array 
     for (var i=0; i<=len; i++) {  //iterating through the length of resolvers array
         ax[i] = new XMLHttpRequest(); //assigning to each item in array new object
         //alert(ax[i]); // shows that object exists 
         ax[i].onreadystatechange = function(){ 
              /*=== 
              problem is above - firebug will show:
              **Uncaught TypeError: Cannot read property 'readyState' of undefined**
              **ax.(anonymous function).onreadystatechangehello.cgi:30** 
              oddly it will still populate divs inner html  with 'loading +1 '
              albeit regardless of readystate code (can be 4 or anything else )
              It perplexes me why i is thought as a function? 
              =====*/
              // alert(i);  //if this is enabled I will see readyState==4 populated correctly
              if (ax[i].readyState != 4) {
                   document.getElementById('return_table_'+i).innerHTML="loading "+i;
              }
              if(ax[i].readyState == 4){
                  // get data from the server response
                  var response_ready=ax[i].responseText;
                  document.getElementById('return_table_'+i).innerHTML = response_ready;
              }
         } 
         ax[i].open("GET","av.pl?resolver=" + arr[i] +"&fqdn=google.com",true); //works 
         ax[i].send(null); //works 
      }

 }
4

1 に答える 1

2

あなたの問題は非常に一般的なものです。JavaScript では、変数はブロック ステートメント レベルではなく、関数レベルでスコープされます。したがって、変数「i」を使用してそのループを反復すると、ループ内で作成する各関数は同じ「i」を共有します。したがって、関数が実際に呼び出されると、「i」の値はループの最後にある値になります。これは、配列の最後を超えたポイントです!

この問題を回避するには、これらの関数を別の関数で作成する必要があります。これを行うためのクリーンな方法は、別のローカル関数を用意することです。

 function makeReadyStateHandler(i) {
     return function() {
          if (ax[i].readyState != 4) {
               document.getElementById('return_table_'+i).innerHTML="loading "+i;
          }
          if(ax[i].readyState == 4){
              // get data from the server response
              var response_ready=ax[i].responseText;
              document.getElementById('return_table_'+i).innerHTML = response_ready;
          }
     };
 }

次に、ループからその関数を呼び出します。

      ax[i].onreadystatechange = makeReadyStateHandler(i);

このような別の関数を使用することで、各ハンドラー関数が、ループ内の正しいポイントで固定された独自の "i" のコピーを持つことが保証されます。この関数は、新しく作成された関数を結果として返します。これをイベント ハンドラーとして使用します。

于 2012-01-01T16:02:26.190 に答える