Take this code, typical node js example of a Http server, to which I've added a delay of 5 seconds to simulate some async work taking place somewhere else:
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}/`);
});
What I would expect is that when I open 5 tabs, let's say with a delay of half a second between opening each, the server should "respond" to each tab more or less with this timings:
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
However, the behaviour I'm seeing is the following:
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
As if the subsequent requests weren't starting to run until the first one has finished. Am I missing something here? I thought the whole point of Node JS was to be able to run async taks from a single thread?
setTimeout doesn't block anything, just like it doesn't block on the client side. You shouldn't confuse for example PHP's sleep function with setTimeout (or setInterval for that matter).
Explanation: setTimeout() is non-blocking which means it will run when the statements outside of it have executed and then after one second it will execute.
The setTimeout function is used to call a function after the specified number of milliseconds. The delay of the called function begins after the remaining statements in the script have finished executing. The setTimeout function is found in the Timers module of Node. js.
You can also prevent the setTimeout() method from executing the function by using the clearTimeout() method. If you have multiple setTimeout() methods, then you need to save the IDs returned by each method call and then call clearTimeout() method as many times as needed to clear them all.
The problem isn't your code or Node.js -- it's how you set up your test.
You wrongly assumed that your browser would make 5 concurrent requests, which is not happening. Different browsers have different behaviors, but typically browsers limit to a very low number the maximum amount of simultaneous connections to a single origin. The HTTP spec gives a suggest maximum. I was actually quite surprised to see Chrome only opening 1 single connection to localhost, as I know Chrome opens 6 to other origins -- just learned something new!
Use a different tool to run your test, one that you can control and know for sure that it's making concurrent requests. Then you'll see the expected behavior.
As an example, I ran your code and tested with Apache Benchmark as shown below. The parameters indicate: -n 10
is to make 10 requests, -c 10
is to use concurrency 10 (ie, make all the ten requests concurrently). As you can see in the results below, the total time taken for all the requests was ~5s (and "time per request" 0.5s):
~ $ 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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With