Node.js - 为啥我的一些回调没有异步执行?

Posted

技术标签:

【中文标题】Node.js - 为啥我的一些回调没有异步执行?【英文标题】:Node.js - Why are some of my callbacks not executing asynchronously?Node.js - 为什么我的一些回调没有异步执行? 【发布时间】:2014-04-05 10:35:42 【问题描述】:

关于使用回调作为 Node 和 http 类的控制流模式的新手问题。根据我对事件循环的理解,所有代码都是阻塞的,i/o 是非阻塞的并使用回调,这是一个简单的 http 服务器和一个伪 rest 函数:

// Require
var http = require("http"); 

// Class 
function REST() ;

// Methods
REST.prototype.resolve = function(request,response,callback) 

    // Pseudo rest function
    function callREST(request, callback) 

        if (request.url == '/test/slow') 
            setTimeout(function()callback('time is 30 seconds'),30000);
         else if (request.url == '/test/foo') 
            callback('bar');
        
    

    // Call pseudo rest
    callREST(request, callback);



// Class
function HTTPServer() ;

// Methods
HTTPServer.prototype.start = function() 

    http.createServer(function (request, response) 

        // Listeners
        request.resume();
        request.on("end", function () 

            // Execute only in not a favicon request
            var faviconCheck = request.url.indexOf("favicon");
            if (faviconCheck < 0)  

                //Print
                console.log('incoming validated HTTP request: ' + request.url);

                //Instantiate and execute on new REST object
                var rest = new REST();
                rest.resolve(request,response,function(responseMsg) 
                    var contentType = 'Content-Type': 'text/plain';
                    response.writeHead(200, contentType); // Write response header
                    response.end(responseMsg); // Send response and end
                    console.log(request.url + ' response sent and ended');
                );
             else 
                response.end();
            
        );
    ).listen(8080);

    // Print to console
    console.log('HTTPServer running on 8080. PID is ' + process.pid);
 

// Process
// Create http server instance
var httpServer = new HTTPServer();

// Start
httpServer.start();

如果我打开浏览器并在一个选项卡中使用“/test/slow”然后在另一个选项卡中使用“/test/foo”访问服务器,我会得到以下行为 - “foo”立即以“Bar”响应,然后迟到 30 秒,“慢”响应“时间为 30 秒”。这是我所期待的。

但是,如果我在浏览器中打开 3 个选项卡并在每个选项卡中连续使用“/test/slow”访问服务器,则“slow”正在被处理并串行/同步响应,因此 3 个响应以 30 秒的间隔出现.如果它们是异步处理的,我希望它们会一个接一个地得到响应。

我做错了什么?

感谢您的意见。

【问题讨论】:

我认为您的浏览器被阻止了。尝试 3 种不同的浏览器。 @cookiemonster 但是,为什么浏览器会阻止请求? @thefourtheye:因为它们指向同一个 url。我现在正在做一些测试,但我似乎想起了一些类似的问题。 @cookiemonster 哦,是这样吗?即使我很惊讶看到这种行为。请分享你的发现:) @thefourtheye:已确认。如果我将callREST 中的if 语句更改为:if (request.url.slice(0,-2) == '/test/slow') ,并向/test/slow/1/test/slow/2/test/slow/3 发送请求,它会按预期工作。 【参考方案1】:

这其实不是服务器的错。您的浏览器正在打开一个连接并在请求之间重新使用它,但一个请求在前一个完成之前无法开始。您可以通过以下几种方式看到这一点:

查看 Chrome 开发工具的网络选项卡 - 最长的条目将显示处于 blocking 状态的请求,直到前两个完成。 尝试在不同的浏览器中打开慢速页面(或在普通和隐身窗口中各一个) - 这会阻止共享连接。

因此,只有当同一个浏览器窗口向同一个服务器发出多个请求时,才会发生这种情况。另外,请注意 XHR (AJAX) 请求将打开单独的连接,以便它们可以并行执行。在现实世界中,这不是问题。

【讨论】:

选择这个作为最完整的答案。经过测试和验证。

以上是关于Node.js - 为啥我的一些回调没有异步执行?的主要内容,如果未能解决你的问题,请参考以下文章

node js 回调函数

Node.js 回调函数

Node.js 回调函数

同步和异步 以及node js 回调函数

node.js 在执行'n'异步回调后执行函数

Node.js 异步编程与连接mysql数据库