javascript - 为什么 setTimeout 会阻止我的 Node.js 应用程序?

标签 javascript node.js asynchronous

以这段代码为例,典型的 Http 服务器的 node js 示例,我在其中添加了 5 秒的延迟来模拟在其他地方发生的一些异步工作:

const http = require('http');

const hostname = '127.0.0.1';
const port = 8080;

http.createServer((req, res) => {
  setTimeout(()=>{
      res.writeHead(200, { 'Content-Type': 'text/plain' });
      res.end('Hello World\n');
  },5000);
}).listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

我期望的是,当我打开 5 个选项卡时,假设在打开每个选项卡之间有半秒的延迟,服务器应该或多或少地按照以下时间“响应”每个选项卡:

t=0s - I open first tab
t=0.5s - I open second tab
t=1s - I open third tab
...
t=5s - First tab stops loading, server has replied
t=5.5s - Second tab stops loading, server has replied
t=6s - Third tab stops loading, server has replied
t=6.5s - Fourth tab stops loading, server has replied
t=7s - Fifth tab stops loading, server has replied

但是,我看到的行为如下:

t=0s - I open first tab
t=0.5s - I open second tab
t=1s - I open third tab
...
t=5s - First tab stops loading, server has replied
t=10s - Second tab stops loading, server has replied
t=15s - Third tab stops loading, server has replied
t=20s - Fourth tab stops loading, server has replied
t=25s - Fifth tab stops loading, server has replied

好像在第一个请求完成之前,后续请求才开始运行。我在这里错过了什么吗?我认为 Node JS 的全部意义在于能够从单个线程运行异步任务?

最佳答案

问题不在于您的代码或 Node.js,而在于您设置测试的方式。

您错误地认为您的浏览器会发出 5 个并发请求,但事实并非如此。不同的浏览器有不同的行为,但通常浏览器将同时连接到单个源的最大数量限制为非常低的数量。 HTTP 规范给出了建议最大值。 实际上我很惊讶地看到 Chrome 只打开了 1 个到 localhost 的单一连接,因为我知道 Chrome 打开了 6 个到其他来源——刚刚学到了一些新东西!

使用不同的工具来运行您的测试,您可以控制并确定它正在发出并发请求。然后你会看到预期的行为。

例如,我运行了您的代码并使用 Apache Benchmark 进行了测试,如下所示。参数表示:-n 10是10个请求,-c 10是并发10(即10个请求全部并发)。正如您在下面的结果中看到的,所有请求的总时间约为 5 秒(“每个请求的时间”为 0.5 秒):

~ $ ab -n 10 -c 10 http://127.0.0.1:8080/
This is ApacheBench, Version 2.3 <$Revision: 1663405 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (be patient).....done


Server Software:
Server Hostname:        127.0.0.1
Server Port:            8080

Document Path:          /
Document Length:        12 bytes

Concurrency Level:      10
Time taken for tests:   5.019 seconds
Complete requests:      10
Failed requests:        0
Total transferred:      1130 bytes
HTML transferred:       120 bytes
Requests per second:    1.99 [#/sec] (mean)
Time per request:       5019.151 [ms] (mean)
Time per request:       501.915 [ms] (mean, across all concurrent requests)
Transfer rate:          0.22 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       0
Processing:  5017 5018   0.3   5018    5018
Waiting:     5008 5008   0.2   5008    5009
Total:       5018 5018   0.2   5019    5019
ERROR: The median and mean for the total time are more than twice the standard
       deviation apart. These results are NOT reliable.

Percentage of the requests served within a certain time (ms)
  50%   5019
  66%   5019
  75%   5019
  80%   5019
  90%   5019
  95%   5019
  98%   5019
  99%   5019
 100%   5019 (longest request)

关于javascript - 为什么 setTimeout 会阻止我的 Node.js 应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35825965/

相关文章:

javascript - 按开始时间排序,按结束时间打破平局

javascript - 使用变量处理字符串sql查询中的单引号

javascript - 在 Node JS 中使用 YQL

node.js - 水线: Access populated value within a model

java - Vert.x 3,请求处理程序 POST、异步 CompletionStage 或 CompletableFuture

javascript - append() "<tr> element"到 "<table> element"二十五次但是运行 HTML 时 <table> 只有 1 行

javascript - 改变 `this.state` 然后立即调用 `setState` 如何中断?

javascript - 如何利用JavaScript和Node.js中的事件循环?

reactjs - 如何调度等待其他异步操作完成的 redux 操作?

python - 如何在 python lambda 中使用 await