Diving into Node.js – A Long Polling Example
Join the DZone community and get the full member experience.
Join For FreeWhat is typical for most of the web servers is that they listen for requests and respond as quickly as possible on every one of them. In fact the speed of the response is one of the main targets of optimization for developers. Fast servers are what everyone needs. From web developers to website visitors!
In the field of the that battle different web servers have different “weapons” to gain time. While this is useful in most of the cases, when it comes to a chat-like applications and Node.js approaches, the response is not always immediately returned. As I described in my posts until now about Node.js, a simple web server may wait for an event to be emitted, and than return the response.
I wrote about how to write the very first server, but than I didn’t described how to make a “non-responding” server. By the term “non-responding” I mean a server that responds not immediately after it has received and parsed/executed the request.
A typical web server, responding immediately on every request, written with Node, this may look like so:
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(8124, "127.0.0.1");
console.log('Server running at http://127.0.0.1:8124/');
The code that shows us that the request is executed and responds in these lines:
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
Actually by commenting/removing those lines you’ll get a server that simply doesn’t respond – ever! This of course is not the main goal, but you can start from somewhere.
var http = require('http');
http.createServer(function (req, res) {
// res.writeHead(200, {'Content-Type': 'text/plain'});
// res.end('Hello World\n');
}).listen(8124, "127.0.0.1");
console.log('Server running at http://127.0.0.1:8124/');
This is how you can hold for a while. Perhaps putting these lines in a conditional statement and periodically checking for some event to occur will do the job.
var http = require('http');
http.createServer(function (req, res) {
if (something) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}
}).listen(8124, "127.0.0.1");
console.log('Server running at http://127.0.0.1:8124/');
Looping Server
As described in the code above if you put the respond into a conditional you can possibly return the response after some event has fired. The only thing is to periodically loop and check for this condition to be true. Assuming your server’s code is in server.js, started with the “node server.js” command, you’ve to put this code into it:
var http = require("http"),
fs = require("fs");
// we create a server with automatically binding
// to a server request listener
http.createServer(function(request, response) {
checkFile(request, response);
}).listen(8124);
function checkFile(request, response)
{
var date = new Date();
if (date-request.socket._idleStart.getTime() > 59999) {
response.writeHead(200, {
'Content-Type' : 'text/plain',
'Access-Control-Allow-Origin' : '*'
});
// return response
response.write('OK', 'utf8');
response.end();
}
// we check the information from the file, especially
// to know when it was changed for the last time
fs.stat('filepath', function(err, stats) {
// if the file is changed
if (stats.mtime.getTime() > request.socket._idleStart.getTime()) {
// read it
fs.readFile('filepath', 'utf8', function(err, data) {
// return the contents
response.writeHead(200, {
'Content-Type' : 'text/plain',
'Access-Control-Allow-Origin' : '*'
});
// return response
response.write(data, 'utf8');
response.end();
// return
return false;
});
}
});
setTimeout(function() { checkFile(request, response) }, 10000);
};
Note: you must change “filepath” with an existing file path in your system.
Here we can read periodically the file’s mtime, which is the modify time. Thus whenever the file is changed the server will return the response. It’s interesting to note that if no change occurs within the timeout period you’ve to return some status message as we did in those lines:
var date = new Date();
if (date-request.socket._idleStart.getTime() > 59999) {
response.writeHead(200, {
'Content-Type' : 'text/plain',
'Access-Control-Allow-Origin' : '*'
});
// return response
response.write('OK', 'utf8');
response.end();
}
The client side should long poll this server. The example bellow is written in jQuery. The only “special” thing is that after receiving the response, you must call the server again.
The Client
The client is nothing new to the jQuery/JavaScript community except you must call again the server when the response is returned:
function callNode() {
$.ajax({
cache : false,
// setup the server address
url : 'http://www.example.com:8124/',
data : {},
success : function(response, code, xhr) {
if ('OK' == response) {
callNode();
return false;
}
// do whatever you want with the response
...
// make new call
callNode();
}
});
};
callNode();
Summary
As Node can hold the response, the only thing you should do is to check periodically for something as in this example this was a file change. Than it’s important to change the client so it can call the server after the response from it is received.
Typically Node can be used for chat-like applications or whatever apps that must deliver real time data, but for sure it is really great software.
Related posts:
- Diving into Node.js – Very First App
- Diving into Node.js – Introduction & Installation
- Read Remote File Content-Type with Zend_Http_Client
Published at DZone with permission of Stoimen Popov, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Trending
-
Microservices With Apache Camel and Quarkus
-
Writing a Vector Database in a Week in Rust
-
How To Approach Java, Databases, and SQL [Video]
-
Structured Logging
Comments