2012-03-27 9 views
0

編集:閉じることができます。 Isn't truly asynchronous, non-blocking javascript impossible?Node.jsは実際にバックグラウンドI/Oタスクを非同期で処理しますか?


var PATH = require ("path"); 
var URL = require ("url"); 

var sleep = function (ms){ 
    var start = new Date().getTime(); 
    while ((new Date().getTime() - start) < ms); 
} 

require ("http").createServer (function (req, res){ 
    if (URL.parse (req.url).pathname === "/1"){ 
     console.log ("tab 1: I'm in"); 
     PATH.exists ("test", function (exists){ 

      sleep (5000); 

      res.writeHead (200, {"Content-Type": "text/plain"}); 
      res.end ("1"); 
      console.log ("tab 1: I'm done"); 
     }); 
    }else{ 
     console.log ("tab 2: I'm in"); 
     res.writeHead (200, {"Content-Type": "text/plain"}); 
     res.end ("2"); 
     console.log ("tab 2: I'm done"); 
    } 
}).listen (80); 
  1. ファイルに内容をコピーします。
  2. ファイルを実行します。
  3. ブラウザで新しいタブを開きます。 URLをlocalhost/1に設定します。まだ行かないでください。
  4. ブラウザで新しいタブを開きます。 URLをlocalhost/2に設定します。まだ行かないでください。
  5. 最初のタブに戻ります。 enterを押して、2番目のタブに変更した直後にenterを押します。

結果:

  • コンソールログ:

    タブ1:私は
    タブ1にいる:私は終わりだ
    タブ2:私は
    タブによ2:完了しました

  • タブ1は結果 "1"を受け取るのを5秒待っています。

  • タブ2は、タブ1が5秒間スリープしているので、5秒間待たなければなりません。

docsは、コード以外のすべてが非同期であると言います。 1つのスレッドのみ。一度に1つのリクエストのみ。リクエストはエンキューされます。

I/Oコールは非同期であると想定されます。コールバックが非同期I/Oプロセスから来た場合、なぜタブ2がタブ1を待たなければならないのですか?

ありがとうございました。

+1

ノード内に偽の 'sleep'メソッドがある* ragequit * – jAndy

答えて

5

sleepがイベントループをブロックしているためです。

setTimemout(function() { /* Code to run */ }, 5000);と交換して、すぐに応答する/2を見てください。

実際のI/Oは非同期ですが、I/Oで実行しているすべてのアクションはイベントループで発生します。何かがイベントループをブロックしている場合は、あなたが言ったように、他のものはすべて待機しなければなりません。

EDIT。より明確にするため、次のASCIIグラフィックをご覧ください。

Event Loop Thread: ------+req1HandlerExistsCall+-------+req1Wait5Sec++++++++++++++++++++++++++req2ExistsCall+-------+req2Immediate+------------- 
     HTTP I/O: -+req1+--------------------------------------+req2+--------------------------------------+req1Response+--------+req2Response+ 
     File I/O: ----------------------------+exists1+----------------------------------------------------+exists2+--------------------------- 

基本的に、各スレッドごとに1つずつです。最初のリクエストハンドラは5秒間ブロックされるので(スピードテストではファイルシステムを叩くのは本質的に不可能です)、2番目のレスポンスは最初のリクエストがほとんど完了するまで処理されません。

+0

次に、exist()関数が同期していますか?次に、ファイルが存在するかどうかをテストする2つの関数があるのはなぜですか? (exists()およびexistsSync())。 Thanks –

+0

いいえ、 '' exists''は非同期ですが、各イベントは1つのスレッドでリニアに実行されるので、 '' sleep''コマンドはすべてのアクションを5秒間ブロックします。より説明しやすいように、私の投稿をASCIIグラフィックで編集してみましょう。 –

+0

ありがとう、私は本当に非同期性と同時性と混同されました。今、node.jsは従来のブラウザのイベントループ(タイムアウト、ajaxなど)と同じように動作することがわかりました。 –

2
  1. あなたはあなたのコードを処理するために、5秒を取っている、すなわち、あなたはあなたのコードで忙しい睡眠メソッドを呼び出しているコード内の任意のI/O呼び出し
  2. を持っていません。そして、処理中は他のものは実行できません

正直なところ、これは本当の質問ですか、それとも単にbashノードにしようとしていますか?

+0

質問は他の質問と同様に本当です。 –

+0

あなたは超賢明でなければなりません。 downvoteを削除してください。それは本当の質問です。 –

1

スリープはブロック方式で実装され、シングルスレッド化されているエンジンで実行されます。

SetTimeoutメソッドはJavaScriptでしばらくお待ちください。

また、JavaScriptではほとんどの場合、処理が完了したときに呼び出される他の関数への関数型付きパラメータで処理されるため、resultHandlerが必要です。

関連する問題