Node.js是否真的异步执行后台I / O任务?

时间:2012-03-27 20:15:48

标签: javascript http node.js asynchronous

编辑:我们可以关闭。 Isn't truly asynchronous, non-blocking javascript impossible?


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. 在浏览器中打开一个新标签页。将网址设置为localhost/1。不要走了。
  4. 在浏览器中打开一个新标签页。将网址设置为localhost/2。不要走了。
  5. 返回第一个标签。按Enter键并在更改到第二个选项卡后立即按Enter键。
  6. 结果:

    • 控制台日志:

      标签1:我在 表1:我已经完成了 表2:我在 表2:我已经完成了

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

    • 标签2也必须等待5秒钟,因为标签1正在休眠5秒钟。

    文档说除了代码之外所有都是异步的。只有一个线程。一次只能有一个请求。请求已入队。

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

    感谢。

3 个答案:

答案 0 :(得分: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+---------------------------

基本上,每个线程一次只能有一个。因为第一个请求处理程序会阻塞5秒钟(并且在速度测试中用手指敲打文件系统基本上是不可能的),所以第二个响应甚至在第一个请求几乎完成之后才开始处理。

答案 1 :(得分:2)

  1. 您的代码中没有任何I / O调用
  2. 您在代码中调用繁忙的睡眠方法,即您的代码需要5秒钟才能处理。虽然它正在处理其他任何可以在该实例上运行的内容
  3. 老实说,这是一个真正的问题还是你只想尝试bash节点?

答案 2 :(得分:1)

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

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

还要考虑一下,在JavaScript中,大多数事情都应该涉及一个resultHandler,因为在完成作业时,函数类型参数会处理为要调用的其他函数。