Node.js真的异步完成后台I/O任务吗

Does Node.js really do the background I/O tasks asynchronously?

本文关键字:任务 后台 js 真的 异步 Node      更新时间:2023-09-26

编辑:我们可以关闭。是不是;难道真的不可能实现异步、无阻塞的javascript吗?


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键,切换到第二个选项卡后立即按enter键

结果:

  • 控制台日志:

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

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

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

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

I/O调用应该是异步的,对吧?那么,如果回调来自异步I/O进程,为什么选项卡2必须等待选项卡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秒钟(在速度测试中,用手指基本上不可能击败文件系统),所以直到第一个请求几乎完成后,才开始处理第二个响应。

  1. 您的代码中没有任何I/O调用
  2. 你在代码中调用了一个繁忙的睡眠方法,即你的代码需要5秒才能处理。当它正在处理时,其他任何东西都不能在该实例上运行

老实说,这是一个真正的问题,还是您只是想抨击node?

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

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

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