Async Express middleware, how does it know Code Answer

Hello Developer, Hope you guys are doing great. Today at Tutorial Guruji Official website, we are sharing the answer of Async Express middleware, how does it know without wasting too much if your time.

The question is published on by Tutorial Guruji team.

So I have my Express (4.0) configuration:

app.get('/api/tracks', (req, res) => {

});

In it I want to query elasticsearch:

app.get('/api/tracks', (req, res) => {
    client.search({
        index: 'someindex',
        type: 'sometype',
        body: {
            query: {
                match_all: {}
            }
        }
    }, (err, resp) => {
        res.json(resp);
    });
});

This is clearly an “async” request because of the callback situation.

How does Express know to hang around till you send something, because by all accounts, the response could have been sent out when search had finished executing…. (way before the ES request had finished)

If Express makes use of like some kind of event use, so calling something like res.end() to signal the end of the response, why doesn’t it do that on all normal get‘s or post‘s and leave them open?

Because:

app.get('/api/profile', (req, res) => {
    res.json({ user: 'callum' });
});

Works normally and the response according to the browser has finished….

Answer

You can do res.json() only once. Consider this example:

var express = require('express');
var app = express();

app.get('/json1', function (req, res) {
  setTimeout(function () {
    res.json({ok:true});
  }, 2000);
});

app.get('/json2', function (req, res) {
  setTimeout(function () {
    res.json({ok:true});
    res.json({ok:true});
  }, 2000);
});

app.listen(3333);

When you access it with:

$ curl http://localhost:3333/json1

You get this after 2 seconds:

{"ok":true}

But if you try to access it with:

curl http://localhost:3333/json2

Then you still get this on your client side:

{"ok":true}

But your server crashes with:

_http_outgoing.js:344
    throw new Error('Can't set headers after they are sent.');
    ^

Error: Can't set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:344:11)

It means that Express waits for the res.json() and finishes the request as soon as it gets one, but after that point you cannot call it second time.

The same happens with res.send() – e.g. see those routes:

app.get('/send1', function (req, res) {
  setTimeout(function () {
    res.send('ok');
  }, 2000);
});

app.get('/send2', function (req, res) {
  setTimeout(function () {
    res.send('ok');
    res.send('ok');
  }, 2000);
});

On the other hand, it seems that you can call res.end() twice and the second call gets ignored:

app.get('/end1', function (req, res) {
  setTimeout(function () {
    res.end('ok');
  }, 2000);
});

app.get('/end2', function (req, res) {
  setTimeout(function () {
    res.end('ok');
    res.end('ok');
  }, 2000);
});

But if you use res.write() instead of res.end() then the request will wait for the res.end() and never finish:

app.get('/end1', function (req, res) {
  setTimeout(function () {
    res.end('ok');
  }, 2000);
});

app.get('/end2', function (req, res) {
  setTimeout(function () {
    res.end('ok');
    res.end('ok');
  }, 2000);
});

But the message actually gets delivered – which you can observe by ending the message by “n” to make curl show it when it arrives:

app.get('/write1', function (req, res) {
  setTimeout(function () {
    res.write('okn');
  }, 2000);
});

app.get('/write2', function (req, res) {
  setTimeout(function () {
    res.write('okn');
    res.write('okn');
  }, 2000);
});

So as you can see, there are certain ways to send data – like res.write() that can be used many times and doesn’t close the connection. There are other ways like res.json() that can be used only once and they implicitly close the connection.

But if you add a route like this one:

app.get('/empty', function (req, res) {
});

Then Express will wait forever with the connection open because it has no way to tell whether res.end() or res.json() will be called in the future. It can only know whether it has been called already or not yet.

We are here to answer your question about Async Express middleware, how does it know - If you find the proper solution, please don't forgot to share this with your team members.

Related Posts

Tutorial Guruji