Automatically Refresh an 'app.get()' in Node.js - node.js

I tried to find this topic everywhere, unsuccessfully.
I have a app.get() code, really simple, that gets one information from a variable that is constantly changing ("equip[id].status"), I want it to check if the variable changed from time to time.
Other option is keep a track on this variable, and when it changes run app.get() again.
My codes:
This is the one I want to refresh:
app1.get("/", function(req,res){
id = 1;
res.render(__dirname + '/connected.html', {equipment: 'Esteira 1', status: equip[id].status, historico: equip[id].hist});
});
And this are the ones that change "status"
app1.get("/open", function(req,res){
id = 1;
equip[id].status = 'Conectado';
equip[id].hist = equip[id].hist + equip[id].status;
var now = new Date();
time = dateFormat(now,"h:MM:ss");
console.log(time+" - Equipment 'Esteira 1' has connected on port 3001");
res.end
});
app1.get("/closed", function(req,res){
id = 1;
equip[id].status = 'Desconectado';
equip[id].hist = equip[id].hist + equip[id].status;
var now = new Date();
time = dateFormat(now,"h:MM:ss");
console.log(time+" - Equipment 'Esteira 1' has disconnected");
res.end
});

The app.get() is a server-side code, and on it's own it has no power over changing the client-side.
In the client-side, you need to employ a javascript code to either poll the server regularly (ajax) or have it actively listen to server for changes through websockets. That way you can also choose to either refresh the whole page or just load the relevant changes (like this very site does!).
You should look into these relevant technologies: javascript, ajax, long-polling, socket.io

Related

Custom Computed Etag for Express.js

I'm working on a simple local image server that provides images to a web application with some JSON. The web application has pagination that will do a get request "/images?page=X&limit&200" to an express.js server that returns the JSON files in a single array. I want to take advantage of the browser's internal caching such that if a user goes to a previous page the express.js returns an ETAG. I was wondering how this could be achieved with express.js? For this application, I really just want the computation of the ETAG to take in three parameters the page, the directory, and the limit (It doesn't need to consider the whole JSON body). Also this application is for local use only, so I want the server to do the heavy lifting since I figured it be faster than the browser. I did see https://www.npmjs.com/package/etag which seems promising, but I'm not sure how to use it with express.js
Here's a boilerplate of the express.js code I have below:
var express = require('express');
var app = express();
var fs = require('fs');
app.get('/', async (req, res) =>{
let files = [];
let directory = fs.readdirSync("mypath");
let page = parseInt(req.query.page);
let limit = parseInt(req.query.limit);
for (let i = 0; i < limit; ++i) {
files.push(new Promise((resolve) => {
fs.readFile(files[i + page * limit].name, (err, data) => {
// format the data so easy to use for UI
resolve(JSON.parse(data));
});
});
}
let results = await Promise.all(files);
// compute an etag here and attach it the results.
res.send(results);
});
app.listen(3000);
When your server sends an ETag to the client, it must also be prepared to check the ETag that the client sends back to the server in the If-None-Match header in a subsequent "conditional" request.
If it matches, the server shall respond with status 304; otherwise there is no benefit in using ETags.
var serverEtag = "<compute from page, directory and limit>";
var clientEtag = req.get("If-None-Match");
if (clientEtag === serverEtag) res.status(304).end();
else {
// Your code from above
res.set("ETag", serverEtag);
res.send(results);
}
The computation of the serverEtag could be based on the time of the last modification in the directory, so that it changes whenever any of the images in that directory changes. Importantly, this could be done without carrying out the fs.readFile statements from your code.

NodeJs Flow Process

i recently started working on nodeJs. But got confused between single thread concept wile using global or var keyword variables across diffrent pages which are inluded using required. Below is my code.
var express = require("express");
var app = express();
var mysql = require("mysql");
var comm_fun = requre("./common_functions");
var global_res = ''; // variable to send the reponse back to browser from any function
var global_req = '';// variables to save request data
app.listen(1234,function(req,res){
console.log("server started");
global_res = res;
global_req = req;
mysql = '';// code to have mysql connection in this variable
});
now, as i can use mysql, global_res and global_req variables in diffrent files which are included. But will these effects the values for another request, as they are global.
for example,
request 1 has value 1 for "global_req",
at same time request 2 comes
request 2 has value 2 for "global_req"
will these two request will collide at any point of time. can at any point of time can "global_req" be overwriten from 1 to 2 , as second request has arrived. Or both are diffrent request and will not collide at any point of time.
Thanks,
Yes, and here's a very simple scenario:
Request 1 comes in, sets global ID to 1
Request 1 then performs some IO-bound operation (e.g. DB query)
Meanwhile request 2 comes in and sets the global ID to 2
The IO-bound operation completes and request 1 continues but the global ID is now 2 and not 1
The argument about Node being single-threaded is only applicable if your application is purely CPU-bound, however, given the majority of Node applications are IO-bound then they are in-effect multi-threading. The problem lies in the fact we can't guarantee the order in which callbacks will return, and with that in mind it's fairly simple to create a race condition e.g.
let global_id = 0;
...
app.use(() => global_id++);
app.post('/create', async (req, res) => {
try {
const exists = db.query(`SELECT id FROM table WHERE id = ${global_id}`);
if (!exists) {
db.query(`INSERT INTO ....`);
}
} catch (e) {
return next(e);
}
});
If 2 requests hit the /create endpoint simultaenously, it would be very unlikely that both would succeed (at least correctly).

Node.js watching a file

I want to print a message whenever the file that I am watching has changed. I am able to do that using console.log but I couldn't figure out how to do that using response.write or similar functions.
var counter = 0;
const
http = require('http'),
fs = require('fs'),
filename = process.argv[2];
var server = http.createServer(function(request, response) {
response.writeHead(200, { 'Content-Type' : 'text/plain' });
counter = counter + 1;
response.end('Hello client ' + Math.round(counter / 2));
});
server.on('listening', function() {
var watcher = fs.watch(filename, function(){
console.log('The file ' + filename + ' has just changed.');
});
});
server.listen(8080);
Also, the reason why I have done that Math.round(counter / 2) is because counter is increasing by 2 each time a client is connected. I was wondering why this is happening and if there is a better technique to resolve this.
For you to be able to do it using response.write it would need to be part of your server request handler function.
File events can occur independently of someone sending a request, so it's handling is independent to that of handling a request. Because of this, there is no associated request for you to write to.
If you want to keep track of all the file change events and then show it to the user whenever they do send a request, consider storing the information about changes in an object outside your handler functions and when the a request takes place, read that object to see if there have been changes and write a response based on it to the user.
If you want to inform an end user that the file has change, for example in a web browser, then you have a number of options, including polling the server or using websockets.
I would recommend you take a look at Server Sent Events
It is easy to implement and there are npm module out there to make it even easier in node.js. e.g. npm sse
You can try node module chokidar
https://github.com/paulmillr/chokidar
it is a gread module for file watching

Get SESSIONID in nodeJS

Now, after some hours of playing around with nodejs and socket.io, I'm getting a couple more problems - one being, that I need to get the sessionID inside node.js, whitout using app.get('/' ... - since that event doesnt seem to fire when socket.io connects, it only fires .on('connection', function( ...
var express = require('express')()
express.set('port', process.env.PORT || 8080)
var server = require('http').createServer(express)
var socket = require('socket.io').listen(server)
server.listen(express.get('port'))
// this event is fired, get('/', ... isnt!
server.on('connection', function(stream) {
// ??
} )
The Session is initially created by the PHP application, as the user logs in. Session data is stored in the database, and the key I need to access that data is the SESSION ID. What's the easiest way to get to it? Like mentioned, I found a couple examples that used app.get('/' ... but I couldnt get that event to fire at all.
Thanks.
If the session data is being stored as a cookie (most likely), then you should be able to re-parse that data during the socket handshake. I posted code for that on this answer, but copied the code here as well:
io.configure(function () {
io.set('authorization', function (handshakeData, callback) {
var cookie = handshakeData.headers.cookie;
// parse the cookie to get user data...
// second argument to the callback decides whether to authorize the client
callback(null, true);
});
});
If the session data is being propagated in the URL, then you may be able to gather this information from handshakeData.url or handshakeData.query. You'll probably have to do your own experimentation.

How to handle multiple chat sessions with Node.js

I am currently developing a chat system using Node.js. My question is, how do I handle multiple chat sessions with Node.js. That's a bit vague so I'll explain...
So for example two people might engage in a chat session. Node.js checks every couple of seconds for new messages. This is simple enough as I can get this to work fine using my code below.
My issue is when another two people at the same time are in another chat session.
At present I am sending two query strings called "chat_id" and "check_date" so it can check for new chat messages after a certain date and time.
Problem is, the "chat_id" and "check_date" are overwritten every time a new chat is started because the server is being used by both chat rooms.
Am I making sense?
My code below:
var chat_id, check_date;
var sys = require("sys"),
http = require("http"),
url = require("url"),
path = require("path"),
fs = require("fs"),
events = require("events");
// Conntect to database
var Client = require('mysql').Client;
var client = new Client();
client.host = 'localhost';
client.port = 3306;
client.database = '****';
client.user = '****';
client.password = '****';
client.connect(function(error, results) {
if(error) {
console.log('Connection Error: ' + error.message);
return;
}
console.log('Connected to MySQL');
});
// Check for chat updates
function getChatUpdates() {
if (typeof(check_date) == 'undefined')
return;
client.query('SELECT name, message FROM chat WHERE chat_id = "' + chat_id + '" AND date_entered > "' + check_date + '"',
function selectCb(error, results, fields) {
if (error) {
console.log('GetData Error: ' + error.message);
client.end();
return;
}
if (results.length > 0) {
for(var i = 0;i<results.length;i++) {
console.log('Name: ' + results[i]['name']);
console.log('Message: ' + results[i]['message']);
}
}
});
}
// Set interval to check for chat updates every 2 seconds
setInterval(getChatUpdates, 2000);
http.createServer(function(request, response) {
// Get the query strings
var uri = url.parse(request.url, true);
chat_id = uri.query.chat_id;
check_date = uri.query.check_date;
console.log('Chat ID: ' + chat_id);
console.log('Last Check: ' + check_date);
// we'll do something here later.
}).listen(8080);
sys.puts("Server running at http://localhost:8080/");
It seems like you are having a PHP background and when programming in node.js you should have a completely different mindset. You should not poll(setInterval(getChatUpdates, 2000);
) for messages, but push(callbacks/events) messages to users on event. I advice you to have a look at socket.io and use a in-memory database like redis(instead of mysql) to store your messages. When you code like this your site will perform much better and is going to be real-time(more). Also I would advice you to use express as your framework to develop websites instead of using raw http module. I don't know if you already know about npm, but you should use that to manage your dependencies.
var chat_id, check_date;
Are global variables. You are going to be overriding the chat_id on every connection (in createServer. You probably need some sort of session storage (to associate a user and their chat) eg. an Array, Redis, etc.
It looks like you trying to use MySQL as message queue. RabbitMQ?

Resources