2017-02-05 10 views
-1

これはnode.jsのlearnyounodeチュートリアル練習9からのものです。なぜ私のコードがデータを順番に印刷しないのか分かりません。learnyounode - ジャグリング非同期 - 異なる注文

let http = require('http'), 
    bl = require('bl'), 
    urlArray = [process.argv[2], process.argv[3], process.argv[4]] 
    results = [] 
    //counter = 0; 

function collectData(i) { 
    http.get(urlArray[i], (res) => { 
     res.pipe(bl((err, data) => { 
      if (err) { 
       return console.log(err); 
      } 
      data = data.toString(); 
      results[i] = data; 
      //counter++; 

      //if (counter === 3) { 
       if (results.length === 3) { 
       results.forEach((result) => { 
        console.log(result); 
       }) 
      } 
     })) 
    }) 
} 

for (let i = 0; i < urlArray.length; i++) { 
    collectData(i); 
} 

forループは、最初のurlから開始し、最後まで順番に進む必要があります。私の理解から、ループの現在の反復で何が起こっても、ループが次の反復に移動するように解決する必要があります。しかし、結果はランダムであるように見えます。コマンドラインで私のソリューションを実行すると、時々結果が整然としたものになることがあります。

編集:これは現在動作している私の解決策です。私はカウンタ変数を追加し、http要求を関数に入れました。

+0

*「ループの現在の繰り返しで起こるものは何でも次の反復に移動するループのために解決しなければならない」* - いいえ、それは特に何非同期ですコードはありません。これは非同期の*定義*です。 – JJJ

+0

@JJJこれは、node.jsのすべてのforループが必ずしも順番に実行されないということですか? – James

+0

いいえ、非同期メソッドが必ずしも順番に解決されるわけではありません。 HTTPリクエストは順番に送信され、コールバックは応答を得るたびに呼び出されます。 – JJJ

答えて

0

httpのget-functionが非同期(async)で実装されているため、実行ごとに異なる結果が得られる理由があります。あなたは正しい順序でリクエストを行っていますが、get-URL上のWebサーバーは即座に応答しません。そこで、基本的

、あなたが呼び出すための2つのURLがある場合:

http://stackoverflow.com

http://google.com

あなたがこの順序でそれらを呼び出すが、Googleは10msのように、この実行良好な応答時間を持って、stackoverflowのを20msのように少し長くする必要があります。まず、googleのコールバック関数が呼び出され、次にstackoverflowのコールバック関数が呼び出されます。

応答時間は実行ごとに異なる場合があります。その結果、実行ごとに異なる結果が発生します。

これはあなたのコールバック関数です:

res.pipe(bl((err, data) => { 
    if (err) { 
     return console.log(err); 
    } 
    data = data.toString(); 
    console.log(data); 
} 
+0

私は思ったそれがforループの中にあったので、それは問題ではないでしょう。JJJのコメントとあなたの答えから、プログラムはすべてが終わったときを知る必要があるようです。これは私がやったことですが、それはまだ動作していないようです。 results [i] = data; if(results.length === 3){ for(let j = 0; j James

+0

あなたは今それをやった方法を投稿してもらえますか?コールバック関数 – Merschi

+0

に反復変数(i)をどのように処理するかわからないので、遅れて申し訳ありません。更新しました。 – James

0

全体の問題は、変数である「私」と非同期呼び出し。この特定のロジックでは、非同期呼び出しのためにiの値を制御することはできません。

コードの問題を理解するには、console.logを次の行の後に出力します。 results [i] = data;

これが問題に私のソリューションです:

var http = require('http'); 

var count =3; 
var contentResults = []; 


function hitRequests(i) { 
    http.get(process.argv[i+1],function(response){ 
     response.setEncoding('utf8'); 

     var entireContent=''; 

     response.on('data', function(chunk){ 
      entireContent += chunk; 
     }); 

     response.on('end', function(chunk){ 

      contentResults[i] = entireContent; 
      count --; 

      if(count <= 0) { 
       printAll(); 
      } 

     }); 

    }).on('error',function(e){ 

     console.log('error'+e); 
    }); 
} 

for(i=1;i<=3;i++) { 
    hitRequests(i); 
} 

function printAll() { 
    contentResults.forEach(function(result){ 
     console.log(result); 
    }); 
} 
+0

@james変数iが反復でどのように動作するかを理解してください。しかし、別の関数を呼び出すときに同じ問題が発生することはありません –

+0

上記の私のソリューションを編集しました。私は別の質問がある。カウンタを使用せず、if(results.length === 3)の条件を持っていれば、うまくいきません。カウンターでは、データが結果配列に追加された後に増減します。私は結果配列の長さを比較している場合、同じ動作しないでしょうか?私は何かを得ていないのですか? – James

+0

私はより明確にすることができるようにあなたの更新されたコードを投稿することができます。 –

関連する問題