简体   繁体   中英

Is the routing of express.router() synchronous?

This has been baffling me... This following test shows that requests are being received asynchronously, responded to asynchronously, yet all requests are first received, then responded to... Given the following 3 files:

package.json

{
    "name": "express-router-sync-test",
    "version": "1.0.0",
    "description": "Testing if express router has sync aspect",
    "scripts": {
        "start": "node server.js"
    },
    "dependencies": {
        "body-parser": "1.16.0",
        "express": "4.14.1",
        "request": "2.79.0"
    }
}

server.js

const express = require('express');
const bodyParser = require('body-parser');
const router = express.Router();
const request = require('request');

// Create our Express application
let app = express();

let port = 1111;

// body parser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

app.use(router);

// Start the server
app.listen(port);
console.log('Server listening on port ' + port + '.');


router.get('/', _get);
router.post('/test', _test);

function _test(req, res) {
    console.log('starting to process request # ', req.body.requestNumber);
    request({
        method: 'GET',
        url: 'http://localhost:1111'
    }, (err, response, body) => {
        console.log('process # ' +  req.body.requestNumber + ' has ended');
    });
}

function _get(req, res) {
    res.json({ success: true });
}

test.js

const request = require('request');

let i;
let len = 500;
let options = {
    method: 'POST',
    url: 'http://localhost:1111/test'
}

for (i = 0; i < len; i++) {
    options.form = { requestNumber: i + 1 };
    request(options, (err, response, body) => {
        if (err) console.log(err);
        if (response) console.log(body)
    }); 
}

Given a dir structure of:

app/
--package.json
--server.js
--test.js

Take the following steps to reproduce the test:

  • in a terminal, navigate to the app dir and run npm install
  • run node server.js
  • open another terminal, navigate to app dir and run node test.js

If you look at the output of the server.js terminal, you will note that all "starting processes" loggings are grouped together, but in an asynchronous order. You will also note that all "process ended" loggings are grouped together, but also in an asynchronous order.

I now ask two questions:

  • Why are the responses delayed until after all requests have been received?
  • Is this happening because I'm flooding myself with requests?

Any information would be greatly appreciated.

EDIT: here is an example log of this test run with 50 requests instead of 500. You'll notice that no request is responded to until all requests have been received. The more requests you send, the longer you wait for the first response.

starting to process request #  1
starting to process request #  2
starting to process request #  3
starting to process request #  4
starting to process request #  5
starting to process request #  6
starting to process request #  9
starting to process request #  8
starting to process request #  7
starting to process request #  10
starting to process request #  12
starting to process request #  11
starting to process request #  13
starting to process request #  17
starting to process request #  16
starting to process request #  15
starting to process request #  14
starting to process request #  21
starting to process request #  19
starting to process request #  20
starting to process request #  18
starting to process request #  22
starting to process request #  23
starting to process request #  25
starting to process request #  24
starting to process request #  27
starting to process request #  28
starting to process request #  26
starting to process request #  32
starting to process request #  31
starting to process request #  30
starting to process request #  29
starting to process request #  36
starting to process request #  35
starting to process request #  33
starting to process request #  34
starting to process request #  40
starting to process request #  38
starting to process request #  39
starting to process request #  37
starting to process request #  44
starting to process request #  42
starting to process request #  43
starting to process request #  41
starting to process request #  45
starting to process request #  46
starting to process request #  47
starting to process request #  49
starting to process request #  48
starting to process request #  50
process # 1 has ended
process # 2 has ended
process # 4 has ended
process # 3 has ended
process # 5 has ended
process # 6 has ended
process # 9 has ended
process # 8 has ended
process # 11 has ended
process # 12 has ended
process # 10 has ended
process # 7 has ended
process # 13 has ended
process # 17 has ended
process # 15 has ended
process # 16 has ended
process # 14 has ended
process # 21 has ended
process # 22 has ended
process # 18 has ended
process # 20 has ended
process # 19 has ended
process # 27 has ended
process # 24 has ended
process # 25 has ended
process # 23 has ended
process # 31 has ended
process # 32 has ended
process # 26 has ended
process # 28 has ended
process # 30 has ended
process # 29 has ended
process # 34 has ended
process # 35 has ended
process # 33 has ended
process # 36 has ended
process # 40 has ended
process # 38 has ended
process # 39 has ended
process # 37 has ended
process # 44 has ended
process # 42 has ended
process # 46 has ended
process # 45 has ended
process # 41 has ended
process # 43 has ended
process # 47 has ended
process # 50 has ended
process # 48 has ended
process # 49 has ended

This following test shows that requests are being received asynchronously, responded to asynchronously, yet all requests are first received, then responded to...

It's not clear what is the surprise here. That the requests are first received and then responded to? It wouldn't make much sense to respond to a request before it is received.

Since this is a very general question then maybe I'll add some general info. First of all asynchronously doesn't necessarily mean out of order, if that is what you assume. Operations can be processed asynchronously and in order or out of order, this is irrelevant to the concurrency model being used.

Now, generally speaking every function that returns a value (unless that value is a promise) works synchronously by necessity, just because it cannot return anything that it doesn't have. In that sense the promise itself is actually created and returned synchronously. What is done asynchronously is the resolution of the promise.

Every function that takes a callback usually works asynchronously but it doesn't have to. The callback can be called synchronously and it sometimes is, like in the callback to the .map() method of arrays and strings. Every function that returns a promise should work asynchronously but it's also possible to resolve the promise synchronously before returning it.

The point is that being synchronous and asynchronous is something quite different from the order of execution and it also depends on whether you use promises or continuation passing style.

For anyone else who comes across this behavior and finds it curious... This is happening because the requests are coming in so quickly that NodeJS is "stuck" in the poll phase of it's Event Loop .

Here is some NodeJS documentation pertaining to the Event Loop and the Polling phase .

Pertinent information in link : "If the poll queue is not empty, the event loop will iterate through its queue of callbacks executing them synchronously until either the queue has been exhausted, or the system-dependent hard limit is reached."

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM