【问题标题】:Does Node.js really do the background I/O tasks asynchronously?Node.js 真的异步执行后台 I/O 任务吗?
【发布时间】:2012-04-11 10:10:06
【问题描述】:

编辑:我们可以关闭。 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. 返回到第一个选项卡。按回车键,在切换到第二个选项卡后立即按回车键。

结果:

  • 控制台日志:

    标签 1:我在
    标签 1:我完成了
    标签 2:我在
    选项卡 2:我完成了

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

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

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

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

谢谢。

【问题讨论】:

  • 在节点中有一个假的sleep 方法是ragequit

标签: javascript http node.js asynchronous


【解决方案1】:

因为你的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 秒(在速度测试中几乎不可能用手指击败您的文件系统),所以在第一个请求几乎完成之前,甚至不会开始处理第二个响应。

【讨论】:

  • 那么,exists() 函数是同步的吗?那么为什么有2个函数来测试文件是否存在呢? (存在()和存在同步())。谢谢
  • 不,exists 是异步的,但每个事件在单个线程上线性执行,因此您的 sleep 命令会阻止所有操作 5 秒。让我用 ASCII 图形编辑我的帖子以便更好地解释。
  • 谢谢,我真的对异步和并发感到困惑。现在我看到 node.js 的工作方式与传统的浏览器事件循环(超时、ajax 等)相同。
  • 好吧,需要注意的是,您可以在 Node.js 中生成 child_processes 并具有实际的并行性(但没有内存共享,只有消息传递,以避免整个锁定/互斥锁复杂性)。
【解决方案2】:
  1. 您的代码中没有任何 I/O 调用
  2. 您正在代码中调用忙睡眠方法,即您的代码需要 5 秒来处理。当它正在处理时,没有其他东西可以在该实例上运行

老实说,这是一个真正的问题还是你只是想抨击节点?

【讨论】:

  • 这个问题和这里的大多数其他问题一样真实。
  • 你一定非常聪明。请删除反对票。这是一个真正的问题。
【解决方案3】:

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

SetTimeout 方法相当于 JavaScript 中等待一段时间的版本。

还要考虑,在 JavaScript 中,大多数事情都应该涉及一个 resultHandler,因为延续是使用函数类型参数处理的,以便在工作完成时调用其他函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-24
    • 2012-11-04
    • 2017-08-30
    • 1970-01-01
    • 2012-09-14
    • 1970-01-01
    • 1970-01-01
    • 2018-07-26
    相关资源
    最近更新 更多