2012-03-27 53 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. 在浏览器中打开一个新选项卡。将网址设置为localhost/2。不要走了。
  5. 回到第一个选项卡。按下回车键并在切换到第二个选项卡后立即按下回车键。

结果:

  • 控制台日志:

    标签1:我在
    标签1:我做
    标签2:我在
    标签2:我完成

  • 选项卡1等待5秒钟以接收结果“1”。

  • 选项卡2还必须等待5秒,因为选项卡1正在休眠5秒钟。

该文档说,除代码外,所有代码都是异步的。只有一个线程。一次只有一个请求。请求被排队。

I/O调用应该是异步的,对吗?那为什么如果回调来自异步I/O进程,为什么选项卡2必须等待选项卡1?

谢谢。

+1

在节点中有一个虚假的“睡眠”方法是* ragequit * – jAndy 2012-03-27 20:20:34

回答

5

因为您的sleep正在阻止事件循环。

将其替换为setTimemout(function() { /* Code to run */ }, 5000);,手表/2立即作出响应。

实际的I/O是异步的,但是您在I/O上执行的所有操作都发生在事件循环中。如果有什么东西阻塞了事件循环,那么其他所有事情都必须等待,就像你说的。

编辑。为更清楚起见,请看下面的ASCII图形:

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

基本上,每个线程一次只有一个。由于第一个请求处理程序阻塞了5秒(并且在速度测试中用手指击打文件系统本质上是不可能的),所以第二个响应甚至在第一个请求差不多完成时才开始处理。

+0

然后,exists()函数是否是同义的?那为什么有2个函数来测试一个文件是否存在? (exists()和existsSync())。谢谢 – 2012-03-27 20:34:59

+0

不,''存在''是异步的,但每个事件都是在一个线程上线性执行的,所以你的''sleep''命令会阻塞所有动作5秒。让我用ASCII图形编辑我的帖子以更好地解释。 – 2012-03-27 21:12:51

+0

谢谢,我真的很混淆异步和并发。现在我看到node.js与传统浏览器事件循环(超时,ajax等)的工作方式相同。 – 2012-03-27 21:33:21

2
  1. 您没有任何I/O调用代码
  2. 要调用代码中的一个繁忙的睡眠方法,即你的代码是用5秒钟时间来处理。虽然它正在处理没有别的东西可以运行在那个实例

老实说,这是一个真正的问题,或者你只是试图打击节点?

+0

这个问题与其他大多数问题一样真实。 – 2012-03-27 20:32:11

+0

你一定是超级聪明的。请删除downvote。这是一个真正的问题。 – 2012-03-27 20:46:30

1

睡眠以阻塞的方式实现,并运行在单线程的引擎上。

SetTimeout方法是在JavaScript中等待一段时间的等效版本。

还要考虑到,在JavaScript中,大部分事情都应该使用resultHandler作为延续,并在函数完成时使用函数类型化参数处理其他函数。