Send flash messages like notifications without reloading page - node.js

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.

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.

Correct url flow for web Java-spark application

My web application is created with Spark Framework
(Connecting on same page as server) the url of the first page is http://localhost:4567/start
From here the user clicks on a button to decide one of four tasks.
The form action button is /start
The server checks everything is okay and then returns the new page for this task (e.g fixsongs) (i.e returns the page contents as a string ) from the page.
post(RoutePath.START, (request, response) -> new ServerStart().processRoute(request, response));//User has picked task on start page
ServerFixSongs ssfs = new ServerFixSongs();
path(RoutePath.STARTFIXSONGS, () ->
{
//Display Page
post(RoutePath.FIX, (request, response) -> ssfs.startTask(request, response)); //User submits form on Options page
});
The problem is url stays the same, i.e is one behind where the user is
Now I have worked out how to solve this, instead of the server returning page
it now does a redirect to /fixsongs.go (this is mapped in routes) which calls method that then returns the page contents as a string and modifys the url.
post(RoutePath.START, (request, response) -> new ServerStart().processRoute(request, response));//User has picked task on start page
ServerFixSongs ssfs = new ServerFixSongs();
path(RoutePath.STARTFIXSONGS, () ->
{
get(RoutePath.GO, (request, response) -> new FixSongsPage(request.session().attribute(FOLDER)).createPage(null, null)); //Display Page
post(RoutePath.FIX, (request, response) -> ssfs.startTask(request, response)); //User submits form on Options page
});
But I have two questions
Is this more cumbersome approach the correct way to do this
Do these additional redirect steps impact performance
Note I am not using templating but creating webpages using j2html
I cannot do a redirect directly to a html file in the first call since the html does not actually exist, the pages are created dynamically.
I have also realised that although when I submit start task from START page i submit a POST request because Im redirecting to STARTFIXSONGS this means at the next stage user can use BACK button to go back to STARTFIXSONGS. I would prefer they could not do this, so does this mean i shoud not be using redirects in this case.
Your question is not really related to Spark or j2html, but rather web-applications in general.
Is this more cumbersome approach the correct way to do this
It depends on what you want. If you want users to be able to navigate using the browser buttons, use the Post-Redirect-Get flow. If you don't want this you should probably be using ajax requests, where you post to the server using JavaScript and the server responds with instructions for updating the DOM (usually in JSON format)
Do these additional redirect steps impact performance
Not enough that you should worry about it. You get one more round-trip, but in 99.9% of cases it doesn't matter. If your target user-base is browsing your page using GPRS on a different continent it would, but that's probably not the case.

Sending new/mutated data back to the page in the same POST request?

Playing around with React and Node/Express what I have is a form with a POST request that sends some state information back to the server, on the server side I mutate/change the state and then send the state back in the same post without a redirect() or a page refresh.
router.post('/ProjectPost', function(req, res, next){
console.log('postin up');
const transform = req.body.incom += 'neewer'
console.log(transform);
res.json({backAtChew : transform});
})
Is this ok? Is it ideal? Does in only work here because of the small amount of data changes? Is this ok for scaling? Having the least amount of major page changes or refreshes is ideal for a SPA so this doesn't seem bad. In my actual application it will be major SQL calls or Oauthentication or API usage or what have you have you so I wanted to make sure before getting the idea that this was a way to go.
The calls to the server are made with axios.js

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.

Automatically accessing a route periodically in express.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.

Resources