Node Js server refreshing page when receiving a JSON update - javascript

My application is a web interface to monitor changes on "objects" processed by the pc and in particular when they get over a particular threshold.
The Node Js server runs on the same pc and has the only use of displaying data on a table, refreshing it when one of them reached a given threshold.
At that point the program that calculates the "objects" opens a socket to the Node Js server and sends the json data.
My issue is to reload the page on the user browser to diplay the new resoults without having the user to manually hit the browser refresh button.
For the server I used the express, express-ejs-layouts and body-parser modules.
This is my server code:
// require our dependencies
var express = require('express');
var expressLayouts = require('express-ejs-layouts');
var bodyParser = require('body-parser');
var app = express();
var port = 3000;
// use ejs and express layouts
app.set('view engine', 'ejs');
app.use(expressLayouts);
// use body parser
app.use(bodyParser.json({extended : true}));
// route our app
var router = require('./app/routes');
app.use('/', router);
// set static files (css and images, etc) location
app.use(express.static(__dirname + '/public'));
// start the server
app.listen(port, function() {
console.log('app started');
});
Leaving aside page estetics (css,images, layouts) the core of the server,
serving GET and POST requests is on the routes.js file that, on GET requests renders the pages passing the JSON data to the javascript page containing the table and on POST requests saves the JSON passed by my "objects" calculator.
This is the routes.js code:
// require express
var express = require('express');
var path = require('path');
// create our router object
var router = express.Router();
// export our router
module.exports = router;
router.post("/", function(request, response) {
global.exportage = request.body;
});
// route for our homepage
router.get('/displayobj', function(req, res) {
//res.send(global.exportage);
res.render('pages/displayobj',{data:global.exportage});
});
How you can see I'm using a quite horrible global variable to pass data but I wanted to keep it as simple as possible.
How could I force the reload on the user browser when a new JSON is received?
I tried using location.reload(true) but I get an error during execution saying: "location is not defined".
The problem, in my opinion, is that the server satisfies the GET request issued by the browser and nothing else happens cause the communication is already completed. I would like not to refresh the page with a fixed interval of time but using the new JSON as triggering event (edited after reading comments).

You cannot do real time communication from server to client with simple HTTP requests. Consider using either long polling or websockets.
The simplest solution for you is to use a library like Socket.io that handles it. When the content need to be refreshed, send an event to the client and then either refresh using window.location.reload() or update the content with the DOM API.

Related

Is there a way to serve files to browser and data to rest requests using the same endpoint?

I've followed this 7 hour tutorial on creating a blog almost to. There is one step that I skipped, because I did not want to use the separate client/server hosting that the tutorial suggests. Instead, I have a single heroku server that serves the client out of the public server:
const app = express();
app.use(express.static('public'))
app.use('/posts', postRoutes);
app.use('/user', userRoutes)
You can see that the app also serves some rest requests to the /posts and /user paths. However, the tutorial also led me to add these paths into the url client-side.
For example, you can access my app at (https://blog-tutorial-888.herokuapp.com), but you will be immediately "redirected" to (https://blog-tutorial-888.herokuapp.com/posts).
I say "redirected" because on the client side, it appears that you are at that site, and the purpose is so that you can do things like navigate to the next page, which will be at (https://blog-tutorial-888.herokuapp.com/posts?page=2).
But if you were to actually go to these links, or refresh the page, you will be hit with the result of the rest request, which is a giant block of text (and this is obviously because I have app.use('/posts', postRoutes)).
Is there a way to get around this somehow? Somehow serve both the html and the rest request at this endpoint?
To have a single server that severs the front and data trough a REST API, you would need to differentiate the paths, for example by adding an /api to urls for getting data, like so:
app.use('/api/posts', postRoutes);
app.use('/api/user', userRoutes);
And then below all your /api handlers add following lines so that for every other request you send that HTML that would load React bundle:
app.get("/*", (req, res) => {
// Make sure it's the correct path to the build folder
res.sendFile(path.join(__dirname, "../client/build/index.html"));
});
Of course don't forgot to add /api in your front end query urls as well, not the routes setup:
fetch("/api/posts")
// or
axios.get("/api/posts")

error 500 with express js routing after on form submit button clicked

I've been working on a messenger chatbot that recommends songs based on the mood of the user and I am stuck on routing a reply to the user after the HTML form for preferences has been filled out...
my HTML code only consists of a form that starts as:
<form action="/postback" method="get">
in my index.js file, i check for the endpoint using:
app.get('/postback', (req, res) => {
this always results in a 500 Internal Service Error in console. Would really appreciate some advice on why this may be happening.
EDIT:
here are other relevant parts of my code:
const
request = require('request'),
express = require('express'),
body_parser = require('body-parser'),
path = require('path'),
app = express().use(body_parser.json()); // creates express http server
here is an image of my file system:
filepath
Change the method to POST. I do believe get doesnt send a request body. Forms should post data not get.

console.log() in client from express server

Is it possible to use console.log() in the backend (I am using express) to output things in the frontend.
for example:
const express = require('express');
const app = express();
client.console.log('Hi');
How would I do it?
Thanks.
There is no built-in support for a server to cause something to show in the client console. I'm not sure what the actual use case for that is since the console is typically a debugging aid, not an actual end-user thing.
In any case, if you want to do that, you would have to have cooperating code on both the client and the server and then how that code works depends upon the context in which you want to put the info in the console.
From a page load
From a page load, the server could embed a small script in the page that would output into the browser console when the page loads and runs.
From an Ajax call
Here, you could include a property in some returned JSON that contains the desired console message and then the client code making the ajax call would have to grab that property and call console.log() with it.
From any random time on the server
If you're not in the context of an existing request from the browser or web page Javascript (as in the previous two points), then you would need some push channel connected between the web page and the server such as a webSocket connection, a socket.io connection or a SSE connection. Then, you could send a message to the client and the client would need some code listening for those incoming messages and then display them in the local console upon receiving them.
try it:
The 'send' method of 'res' object of Express, is one of so many ways to send a response to client in the request event.
const express = require('express')
const app = express()
app.get('/test', (req, res) => {
return res.send('Hello world!')
})
There is no support as jfriend00 said, but there is a way to go around this.
So lets say the user requests /test
You want to displayin his console Hello World
So you do:
const express = require('express')
const app = express()
app.get('/test', (req, res) => {
return res.send('<script>console.log(Hello world!)</script>')
})
And that acts as a full client console log. There ya go. (Single Time)
Or setup socket.io as jfriend said in his post if you want to constantly post console messages (multiple times).

Passing data from mongodb to my front end application

I have a MongoDB on a web server and I have a Mean stack web application. Within the MongoDB, I have a bunch of data that I want to pass to my web application. I have looked into options, but I'm a little unsure as to which route to take to make this happen. I have considered using socket.io to set up a listener on my web server to open up a connection with my DB, and then making an API call or direct DB connection to return my data.
I should add that my app is based on the mean.io boilerplate code.
My question is where within my stack do I need to put the socket.io code?
Would it be wise to include the socket.io code at the root of my application or only in the packages/modules that require the data to be passed from my web server to my application?
And finally, is socket.io even the preferred route to take? Is there another method to achieve this that makes more sense such as express.js?
There's no need to use socket.io unless you want real-time constant, persistant streaming of information from your database to your front-end.
First in your express app, connect to the db with https://github.com/mongodb/node-mongodb-native. Then, you can just set up a JSON endpoint route for the data to get sent to. Then the client webpage that needs the data simply sends an XHR request to the JSON page.
EDIT: OP does want to use socket.io.
If you want to use socket.io, you have to include it on both the server and the client.
Server-side:
const express = require('express');
const app = express();
const server = require('http').Server(app);
// socket.io
const io = require('socket.io').listen(server);
// handling socket.io requests
io.on('connection', (socket) => {
log.info('new connection.');
socket.emit('data', {/** whatever data you need to send **/});
socket.on('disconnect', (e) => {
log.info('user disconnected.');
});
});
Client-side:
Be sure to include socket.io in the html file (get it from the website). Then, in your client-side js:
const socket = io();
socket.on('connect', () => {
console.log('connected to server.');
});
socket.on('disconnect', () => {
console.log('disconnected.');
});
socket.on('data', (data) => {
// this is where you receive the data
// do something with your data
});
You should create a route in Express and then, request that route from your angular SPA with an http module, like $http ou Restangular.
Take a look at this article https://scotch.io/tutorials/setting-up-a-mean-stack-single-page-application

How are HTTP responses managed by Node JS express?

Having this simple express app example:
var express = require('express')
var app = express()
app.use(express.static(__dirname+'/public'))
app.get('/', function(request,response) {
response.send("This wont matter if we got an index.hml after all")
})
app.listen(2311, function() {
console.log("app escuchando en Maricela DDMM")
})
And at /public I got an index.html.
When I get rid of such html the string in the send() method will be sent, received and rendered at browser.
What does actually happen with the response.send() string talking about the HTTP response, as the HTML is which is send and so rendered at browser?
Express goes through the chain of middleware in the order in which it was added. You have added express.static as the first middleware, so it will be ran first.
In the event express.static cannot find a file, it calls next(), allowing the next bit of middleware to run. This is your handler set up with app.get('/' //..., which sends the data as you have told it to.
I think it basically sets up the header information based on the parameter in send and then send the http response

Categories