Automatically accessing a route periodically in express.js - node.js

I am writing a node/express app that uses the request module get the json data from a url when a route is hit. Also I want to continuously get the data without hitting the reload button from the browser.Is there a way to automatically access the route periodically.

You can have Javascript in the browser that uses setInterval() to repeatedly call a function that makes an Ajax call to your server, fetches new data from your server and then inserts it into the page.
If you just want you page to reload automatically, you can use the meta refresh tag. Example:
<meta http-equiv="refresh" content="3;url=http://www.mozilla.org/">
Or, if your question is really about how to you just regular do some operation in node.js, then you can just use setInterval() within node.js to call some function every xxx ms.
// execute a function every 5 seconds
setInterval(function() {
// do something here
}, 5000);
If you want the code that is execute regularly to be the same code that a route uses, then put that code in a function and call that function from both the interval timer and from your route. To fully automate an actual route call, you'd have to make a request to your own http server that would create the request and response objects for you, but that is probably not what you really need to do.

Related

running function after res.send

I'm trying to run this code
module.exports = async (req, res, next) => {
res.set('Content-Type', 'text/javascript');
const response = {};
res.status(200).render('/default.js', { response });
await fn(response);
};
fn is a function that calls an api to a service that will output to the client something. but its dependent on the default.js file to be loaded first. How can do something like
res.render('/default.js', { response }).then(async() => {
await fn(response);
};
tried it, but doesn't seem to like the then()
also, fn doesn't return data to the client, it calls an api service that is connected with the web sockets opened by the code from default.js that is rendered.
do i have to make an ajax request for the fn call and not call it internally?
any ideas?
Once you call res.render(), you can send no more data to the client, the http response has been sent and the http connection is done - you can't send any more to it. So, it does you no good to try to add something more to the response after you call res.render().
It sounds like you're trying to put some data INTO the script that you send to the browser. Your choices for that are to either:
Get the data you need to with let data = await fn() before you call res.render() and then pass that to res.render() so your template engine can put that data into the script file that you send the server (before you send it).
You will need to change the script file template to be able to do this so it has appropriate directives to insert data into the script file and you will have to be very careful to format the data as Javascript data structures.
Have a script in the page make an ajax call to get the desired data and then do your task in client-side Javascript after the page is already up and running.
It looks like it might be helpful for you to understand the exact sequence of things between browser and server.
Browser is displaying some web page.
User clicks on a link to a new web page.
Browser requests new web page from the server for a particular URL.
Server delivers HTML page for that URL.
Browser parses that HTML page and discovers some other resources required to render the page (script files, CSS files, images, fonts, etc...)
Browser requests each of those other resources from the server
Server gets a request for each separate resource and returns each one of them to the browser.
Browser incorporates those resources into the HTML page it previously downloaded and parsed.
Any client side scripts it retrieved for that page are then run.
So, the code you show appears to be a route for one of script files (in step 5 above). This is where it fits into the overall scheme of loading a page. Once you've returned the script file to the client with res.render(), it has been sent and that request is done. The browser isn't connected to your server anymore for that resource so you can't send anything else on that same request.

Send flash messages like notifications without reloading page

I am trying to implement flash messages on a page in such a way, that they act like status updates to something a user has submitted on that page. In detail, there is a form on that page and once the user pressed submit, it is posted to a route which handles processing, which however takes some time.
During that processing, I would like to give status updates on the very same page, ideally without reloading the page all the time.
As an extreme example, how could something like this work:
app.get('/index', function(req,res) {
for (var i = 0; i < 100; i++) {
//send a flash every 2 seconds
setTimeout(function(i) {
req.flash('This is ' + i);
}, 2 * 1000 * i, i);
};
res.render('../views/index.ejs');
})
Is this possible? I had a look at 'express-flash-notification', for which I am unsure though if it can do this.
Generally flash notifications add a bit of extra information when you're templating a new page. Libraries such as express-flash-notification won't be much use if you'd rather not reload the page.
The common approach for this scenario is to make a HTTP call in the browser using JavaScript and dynamically update the DOM with with the returned information. You might choose to use something like AJAX (found in jQuery) for this.
The general flow would be this, but you'd tailor it for your specific needs.
Send up the form using an AJAX call from frontend JS, (perhaps you're processing an image or something).
The server sends back a 200 OK response to indicate the upload was successful.
The frontend then makes a HTTP request every few seconds to the server to ask for a status update. This is returned as json (res.json({})). The frontend JS then displays this as needed.
You may choose to use something like web sockets for this status update as well, but if this is your first time approaching frontend AJAX calls then I'd suggest polling (making a request once every few seconds) for now.

Routed page won't render if callback contains process.exit

I'm trying to render a page on a web browser and then exit the Node.js express webserver that served up the page. The code I'm using in the function that is called to do this is:
var express = require('express');
var router = express.Router();
router.get('/restart', function(req, res, next) {
res.render('resetTimer', {}, function() {
console.log("Render resetTimer page and exit.");
process.exit(); // kill Express webserver
});
});
However, I'm getting
This site can’t be reached
localhost refused to connect.
in the web browser, which suggests that the exit is happening before the web page is rendered, even though the exit command is in a callback. If I comment out the process.exit command I see the console log message, but if I don't comment it out, the page isn't rendered and the log message isn't output.
What am I missing?
The res.render() callback is called when the page has been handed off to the response stream, even though it may not yet have been fully delivered to the client. So, if you kill the process at that point, the client delivery may not complete.
I can think of two ways to work around this:
Create a listener for the close event on the response stream and when you get that event, you will know that everything has been sent and you can shut down your server. This will not allow for any other page resources that might need to be loaded (images, style sheets, fonts, etc...) since they may be requested after the page had loaded.
Put an ajax call in the page itself so that AFTER the page loads, it makes the ajax call and then you don't actually restart your server until you get the ajax call. If you don't make the Ajax call until the window load event, then you could also make sure that all other page resources were loaded before rebooting the server.
Note that either of these options allow all sorts of DOS attacks on your server (causing it to reboot whenever an attacker wants).

node.js - express - render multiple views

I'ld like to send two successive ejs page to the client using the following code:
app.post('/', function(req,res) {
res.render('yourDemandIsBeingProceed.ejs');
//some code which require time (open an external programm, run a script, edit a response)
res.render('hereIsYourResult.ejs');
res.end();
});
So, once once the client post his form, he receives a page asking him to wait for a few seconds and then the page containing the response is send.
any suggestion?
many thx
What you can do is have client-side code in yourDemandIsBeingProceed.ejs when the page loads that performs a get/post request to a different endpoint. When the result from that is received, hide/show different elements inside yourDemandIsBeingProceed.ejs so it looks more like hereIsYourResult.ejs
What you really should do is have the user submit information via front end AJAX and put up a loading graphic until the JSON response gets back. AJAX was developed for situations exactly like this.

React JS isomorphic render

ReactJS, original Flux, react-router, nodeJS, socket.io
Everything is up to date.
If i'm switching off javascript in browser, only static code is being rendered.
During server side render ComponentWillMount and render methods being fired up, but not ComponentDidMount.
Even if I'm putting Flux logic into ComponentWillMount method, nothing happen: action is called, but socket.io doesn't send request to server to get data from database. Which means, no data being retrieved from database and nothing useful for search engines is being rendered.
If javascript is enabled, everything works perfect.
Here the important pieces of code:
Component. Add listener and call action:
componentDidMount() {
StoreUser.addChangeListener(this._onChange);
Actions.getUser(this.props.params.userid)
}
Client's action asks server for user data:
function _getUser (userid) {
socket.emit('getUser', userid)
}
up until this place server-side rendering works, but server itself doesn't received getUser event, so nothing happens further.
Again, if javascript is enabled in browser, all this works fine. Server receives this call and returns user's data.
How do i make server receive this event, return user's data and render it before sending to client?
As alternative, may be there is different way to make it SEO friendly?
React's componentDidMount lifecycle hook is not called server-side, as stated in the docs.
If you need to fetch data and use it server-side in the render method of a component, you need to pass this data as props during the initial render. This means, you cannot fetch it either during componentWillMount, even if the hook is called.
To achieve what you want, you need your server-side code to:
determine what components will be rendered
dispatch the proper actions so that your store will be properly populated
render your components only then - as the data is available to pass to your components in an initial render
The details on how to achieve that would of course depend on your flux implementation, the framework you use server-side, etc.

Resources