节点。为什么我的一些回调没有异步执行?

时间:2022-05-26 20:19:28

Noob question on using callbacks as a control flow pattern with Node and the http class. Based on my understanding of the event loop, all code is blocking, i/o is non-blocking and using callbacks, here's the a simple http server and a pseudo rest function:

关于使用回调作为带有节点和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();

If I open up a browser and hit the server with "/test/slow" in one tab then "/test/foo" in another, I get the following behavior - "foo" responds with "Bar" immediately and then 30 secs late, "slow" responds with "time is 30 seconds". This is what I was expecting.

如果我打开一个浏览器,用“/test/slow”在一个标签中点击服务器,然后在另一个标签中“/test/foo”,我得到以下行为——“foo”立即用“Bar”响应,然后30秒延迟,“slow”用“time is 30 seconds”响应。这正是我所期待的。

But if I open up 3 tabs in a browser and hit the server with "/test/slow" successively in each tab, "slow" is being processed and responds serially/synchronously so that the 3 responses appear at 30 second intervals. I was expecting the responses right after each other if they were being processed asynchronously.

但如果我在浏览器中打开3个选项卡,并在每个选项卡中连续地以“/test/slow”点击服务器,“slow”将被处理并以串行/同步方式响应,以便3个响应以30秒的间隔出现。如果响应是异步处理的,那么我希望它们彼此对应。

What am I doing wrong?

我做错了什么?

Thank you for your thoughts.

谢谢你的想法。

1 个解决方案

#1


3  

This is actually not the server's fault. Your browser is opening a single connection and re-using it between the requests, but one request can't begin until the previous finishes. You can see this a couple of ways:

这实际上不是服务器的错误。您的浏览器正在打开一个连接并在请求之间重用它,但是一个请求直到前面的完成才能开始。你可以从以下几个方面来看:

  • Look in the network tab of the Chrome dev tools - the entry for the longest one will show the request in the blocking state until the first two finish.
  • 查看Chrome开发工具的network选项卡——最长的一个条目将以阻塞状态显示请求,直到前两个完成。
  • Try opening the slow page in different browsers (or one each in normal and incognito windows) - this prevents sharing connections.
  • 尝试在不同的浏览器中打开慢速页面(或者在普通的和不可见的窗口中各打开一个)——这可以防止共享连接。

Thus, this will only happen if the same browser window is making multiple requests to the same server. Also, note that XHR (AJAX) requests will open separate connections so they can be performed in parallel. In the real world, this won't be a problem.

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

#1


3  

This is actually not the server's fault. Your browser is opening a single connection and re-using it between the requests, but one request can't begin until the previous finishes. You can see this a couple of ways:

这实际上不是服务器的错误。您的浏览器正在打开一个连接并在请求之间重用它,但是一个请求直到前面的完成才能开始。你可以从以下几个方面来看:

  • Look in the network tab of the Chrome dev tools - the entry for the longest one will show the request in the blocking state until the first two finish.
  • 查看Chrome开发工具的network选项卡——最长的一个条目将以阻塞状态显示请求,直到前两个完成。
  • Try opening the slow page in different browsers (or one each in normal and incognito windows) - this prevents sharing connections.
  • 尝试在不同的浏览器中打开慢速页面(或者在普通的和不可见的窗口中各打开一个)——这可以防止共享连接。

Thus, this will only happen if the same browser window is making multiple requests to the same server. Also, note that XHR (AJAX) requests will open separate connections so they can be performed in parallel. In the real world, this won't be a problem.

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