In Node.js, suppose serving a request takes time. So upon receipt of the request the server wants to response back with "I revived your request and I will get back to you soon". Then once the processing the request is over, the server wants to, this time, get back to the client with the actual response . How can we do that? The code snippet below issues error ( connection closed or something ).
'use strict';
var http = require('http');
var numberOfRequests = 0;
http.createServer(function (request, responce) {
request.n = numberOfRequests;
console.log('Request number ' + numberOfRequests + ' recioved!');
responce.writeHead(200);
responce.write("soon we will get back to you for your request# " + request.n);
responce.end();
setTimeout(function () {
responce.writeHead(200);
responce.write("Responce to your request# " + request.n);
console.log("Responce to the request# " + request.n);
responce.end();
}, 5000);
numberOfRequests++;
}
).listen(8080);
console.log('listening ...');
In Node.js, suppose serving a request takes time. So upon receipt of the request the server wants to response back with "I revived your request and I will get back to you soon". Then once the processing the request is over, the server wants to, this time, get back to the client with the actual response . How can we do that? The code snippet below issues error ( connection closed or something ).
'use strict';
var http = require('http');
var numberOfRequests = 0;
http.createServer(function (request, responce) {
request.n = numberOfRequests;
console.log('Request number ' + numberOfRequests + ' recioved!');
responce.writeHead(200);
responce.write("soon we will get back to you for your request# " + request.n);
responce.end();
setTimeout(function () {
responce.writeHead(200);
responce.write("Responce to your request# " + request.n);
console.log("Responce to the request# " + request.n);
responce.end();
}, 5000);
numberOfRequests++;
}
).listen(8080);
console.log('listening ...');
Share
Improve this question
asked Oct 2, 2017 at 23:17
Waterfr VillaWaterfr Villa
1,3171 gold badge13 silver badges36 bronze badges
5
- 1 you can't, the end. You only get one response per request using the HTTProtocol, so you'll just have to schedule more requests if the response is "not yet", or set up a direct socket connection so that the client and server can municate using a push notification protocol rather than the standard HTTP. – Mike 'Pomax' Kamermans Commented Oct 2, 2017 at 23:18
- @Mike'Pomax'Kamermans please elaborate more – Waterfr Villa Commented Oct 2, 2017 at 23:20
- There's nothing to elaborate: "No: HTTP does not let you send multiple responses. One request, which is considered handled when it gets one response". If you want to do more than that, you'll have to design either a RESTful architecture that works with that, or you need to use a different protocol that allows arbitrary munication like websockets. – Mike 'Pomax' Kamermans Commented Oct 2, 2017 at 23:23
- Not to mention that you can use asynchronicity in the client to have the client do other stuff (like display a spinner) while it waits for a request to finish. The server can also be async so that if pleting the building of the response is slow, to handle other requests while waiting for previous responses to finish. – cowbert Commented Oct 2, 2017 at 23:33
- Socket.io will be the good solution for this problem – Vishnu Mishra Commented Oct 3, 2017 at 1:12
2 Answers
Reset to default 4You can't send two responses to the same request. You can only send one fully formed response per request. That's the http specification.
The only work-arounds for your issue that I know of are:
Use http in a flushed streaming mode. Here, you send part of the response, flush it out so you know it is sent and you have a special type of client on the other end that is reading partial responses and interpreting them (not the usual way that http responses are read and not what a browser does on its own).
Use a websocket or socket.io connection to update the client with progress before you finally send the actual http response. The user would connect a socket.io connection, then make a long running http request, then receive regular progress on the socket.io connection, then receive the http response when it was done. This can be done simply in any web page without much difficulty. The only main problem to solve is you have to install a method of associated a webSocket or socket.io connection with an ining http connection (which can usually be done via a session cookie) so you know which webSocket or socket.io connection is associated with the http request that just arrives.
Use some other server-push scheme to "push" the second response to the client.
Implement client polling. Send an initial http response that instructs the client to check back in NN ms to see if there is more to the response. When the client checks back again NN ms later, you either have the final response for them and send it or you respond again tell them to to check back again in NN ms, etc...
You are looking for Server-Sent-Events (SSE), of course you can send chunked data, just don't call res.end()
until the final piece of data is sent. And by the way, you can only send headers one time. See this example:
res.writeHead(200);
res.write("The first piece of data");
setTimeout(()=>{
res.write("This piece of data will be sent in 1 second.");
res.end("Ok, all data has be send, now close the connection.");
}, 1000);