Question: When getting JSON data via NodeJS, how would I update my EJS template via ExpressJS?

Question

When getting JSON data via NodeJS, how would I update my EJS template via ExpressJS?

Answers 2
Added at 2016-12-21 23:12
Tags
Question

I am calling some APIs using NodeJS and passing them to my EJS template via ExpressJS with this code:

app.get('/', function (req, res) {
res.render('routes/index', {
    plLoopTimes: plLoopTimes,
    pl54Times: pl54Times
})
});

In this instance, plLoopTimes and pl54Times are arrays that have been populated by the JSON that I got from the APIs. In my EJS template, I can simply get the data by running forEach on both arrays. The issue that I am facing is when I am starting my node server for the first time, I get fresh data from the APIs, and that fresh data gets fed into the EJS template, but I want to poll the APIs every minute and get fresh data. Now, I do use setInterval() on my server-side script to call the API every minute, but I can't figure out how to pass that fresh data into the EJS template without refreshing the entire page, which I don't want to do. I have attempted to create a client-side script to change the innerHTML of the element I want to display the data, but if I enter EJS syntax into the script file and pass that into innerHTML, the EJS template does not express that syntax and instead, my script just outputs the EJS string into the page. So, does anyone have any suggestions as to how to update the variables from the server-side code into the EJS template on the client-side?

Answers to

When getting JSON data via NodeJS, how would I update my EJS template via ExpressJS?

nr: #1 dodano: 2016-12-22 02:12

I think you're doing it wrong. If you need real-time behavior, just use the right tools for that. For this need, I would use SocketIO. If you need old browser support you can do it through simply ajax too, but the benefit of web sockets over ajax is big.

Socket.io

This is a simple SocketIO server that send data to all clients every 1 minute.

import socketio from 'socket.io';
import { DataRepository } from 'repositories';


const server = http.createServer();
const io = socketio(server);

io.on('connection', (client) => {
  ((interval = 60000, io) => {
    setInterval(() => {
      const data = DataRepository.fetch();
      client.emit('new', data);
    }, interval);
  })();
});

All clients just need to create an instance of SocketIO and listen for new:

const socket = io('http://yoursite.com:port');
socket.on('emit', data => {
  updateView(data);
});

function updateView ({ plLoopTimes, pl54Times}) {
  plLoopTimes.forEach(t => {
    // update things
  });
  pl54Times.forEach(t => {
    // update things
  });
}

Fallback

Another approach -more classic- is for the interval to be defined on the client instead of the server. So, every time that clients request a new version of the view the server render the view to string and send back to the client.

Here we only need to define a simple route to point a view:

router
  .get('/looptimes', (req, res) => {
    const { plLoopTimes, pl54Times } = DataRepository.fetch();
    // render the file 'looptimes.ejs' to string
    const view = ejs.render('looptimes', {
      plLoopTimes, pl54Times
    });
    res.type('.html');
    res.send(view);
  });

In the frontend you only need to update the HTML.

nr: #2 dodano: 2016-12-22 02:12

You've got most of it right, assuming that you aren't running into a race condition where the json isn't actually ready when you receive a request for the page. To access plLoopTimes and pl54Times in your template if you're passing them to res.render() like that you just need to do something like:

<%= pl54Times.some.property %>

Or if you want to loop over an array of items in that json you can do this:

<% for(var i=0; i < arrayName.length; i++) { %>
    <div><%= arrayName[i].some.property.to.display %></div>
<% } %>

Hope this helps!

Source Show
◀ Wstecz